Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2012-10-15 17:54:10 (GMT)
committer Walter Bender <walter.bender@gmail.com>2012-10-15 17:54:10 (GMT)
commitaf8c24470530d09e93dab30923f98119713fa2b3 (patch)
tree196ed4300a6eff8bf836a1ba3561da4e71f69904
parent8be4d415d653fe140e2fcb03fa5f309ab4096b22 (diff)
removing gtk2 code from repository
-rw-r--r--gtk2/StoryActivity.py404
-rw-r--r--gtk2/game.py265
-rw-r--r--gtk2/grecord.py244
-rw-r--r--gtk2/setup.py32
-rw-r--r--gtk2/sprites.py459
-rw-r--r--gtk2/toolbar_utils.py164
-rw-r--r--gtk2/toolbar_utils.py~165
-rw-r--r--gtk2/utils.py61
8 files changed, 0 insertions, 1794 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
diff --git a/gtk2/game.py b/gtk2/game.py
deleted file mode 100644
index c1bc398..0000000
--- a/gtk2/game.py
+++ /dev/null
@@ -1,265 +0,0 @@
-# -*- coding: utf-8 -*-
-#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 cairo
-import os
-import glob
-from random import uniform
-
-from gettext import gettext as _
-
-import logging
-_logger = logging.getLogger('search-activity')
-
-try:
- from sugar.graphics import style
- GRID_CELL_SIZE = style.GRID_CELL_SIZE
-except ImportError:
- GRID_CELL_SIZE = 0
-
-from sprites import Sprites, Sprite
-
-
-DOT_SIZE = 40
-COLORS = ['#000000', '#a00000', '#907000', '#009000', '#0000ff', '#9000a0']
-
-
-class Game():
-
- def __init__(self, canvas, parent=None, path=None,
- colors=['#A0FFA0', '#FF8080']):
- self._canvas = canvas
- self._parent = parent
- self._parent.show_all()
- self._path = path
-
- self._colors = ['#FFFFFF']
- self._colors.append(colors[0])
- self._colors.append(colors[1])
-
- self._canvas.set_flags(gtk.CAN_FOCUS)
- self._canvas.connect("expose-event", self._expose_cb)
-
- self._width = gtk.gdk.screen_width()
- self._height = gtk.gdk.screen_height() - (GRID_CELL_SIZE * 1.5)
- self._scale = self._height / (3 * DOT_SIZE * 1.2)
- self._scale /= 1.5
- self._dot_size = int(DOT_SIZE * self._scale)
- self._space = int(self._dot_size / 5.)
- self.we_are_sharing = False
-
- self._start_time = 0
- self._timeout_id = None
-
- # Find the image files
- self._PATHS = glob.glob(os.path.join(self._path, 'images', '*.svg'))
-
- # Generate the sprites we'll need...
- self._sprites = Sprites(self._canvas)
- self._dots = []
- yoffset = self._space * 2 # int(self._space / 2.)
- for y in range(3):
- for x in range(3):
- xoffset = int((self._width - 3 * self._dot_size - \
- 2 * self._space) / 2.)
- self._dots.append(
- Sprite(self._sprites,
- xoffset + x * (self._dot_size + self._space),
- y * (self._dot_size + self._space) + yoffset,
- self._new_dot_surface(color=self._colors[0])))
- self._dots[-1].type = -1 # No image
- self._dots[-1].set_label_attributes(72)
-
- def _all_clear(self):
- ''' Things to reinitialize when starting up a new game. '''
- if self._timeout_id is not None:
- gobject.source_remove(self._timeout_id)
-
- for dot in self._dots:
- if dot.type != -1:
- dot.type = -1
- dot.set_shape(self._new_dot_surface(
- self._colors[abs(dot.type)]))
- dot.set_label('?')
- self._dance_counter = 0
- self._dance_step()
-
- def _dance_step(self):
- ''' Short animation before loading new game '''
- for dot in self._dots:
- dot.set_shape(self._new_dot_surface(
- self._colors[int(uniform(0, 3))]))
- self._dance_counter += 1
- if self._dance_counter < 10:
- self._timeout_id = gobject.timeout_add(500, self._dance_step)
- else:
- self._new_game()
-
- def new_game(self):
- ''' Start a new game. '''
- self._all_clear()
-
- def _new_game(self):
- ''' Select pictures at random '''
- for i in range(3 * 3):
- self._dots[i].set_label('')
- self._dots[i].type = int(uniform(0, len(self._PATHS)))
- _logger.debug(self._dots[i].type)
- self._dots[i].set_shape(self._new_dot_surface(
- image=self._dots[i].type))
-
- if self.we_are_sharing:
- _logger.debug('sending a new game')
- self._parent.send_new_game()
-
- def restore_game(self, dot_list):
- ''' Restore a game from the Journal or share '''
- for i, dot in enumerate(dot_list):
- self._dots[i].type = dot
- self._dots[i].set_shape(self._new_dot_surface(
- image=self._dots[i].type))
-
- def save_game(self):
- ''' Return dot list for saving to Journal or
- sharing '''
- dot_list = []
- for dot in self._dots:
- dot_list.append(dot.type)
- return dot_list
-
- def set_sharing(self, share=True):
- _logger.debug('enabling sharing')
- self.we_are_sharing = share
-
- def _grid_to_dot(self, pos):
- ''' calculate the dot index from a column and row in the grid '''
- return pos[0] + pos[1] * 3
-
- def _dot_to_grid(self, dot):
- ''' calculate the grid column and row for a dot '''
- return [dot % 3, int(dot / 3)]
-
- def _expose_cb(self, win, event):
- self.do_expose_event(event)
-
- def do_expose_event(self, event):
- ''' Handle the expose-event by drawing '''
- # Restrict Cairo to the exposed area
- cr = self._canvas.window.cairo_create()
- cr.rectangle(event.area.x, event.area.y,
- event.area.width, event.area.height)
- cr.clip()
- # Refresh sprite list
- self._sprites.redraw_sprites(cr=cr)
-
- def _destroy_cb(self, win, event):
- gtk.main_quit()
-
- def export(self):
- ''' Write dot to cairo surface. '''
- w = h = int(4 * self._space + 3 * self._dot_size)
- png_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h)
- cr = cairo.Context(png_surface)
- cr.set_source_rgb(192, 192, 192)
- cr.rectangle(0, 0, w, h)
- cr.fill()
- for i in range(9):
- y = self._space + int(i / 3.) * (self._dot_size + self._space)
- x = self._space + (i % 3) * (self._dot_size + self._space)
- cr.save()
- cr = gtk.gdk.CairoContext(cr)
- cr.set_source_surface(self._dots[i].cached_surfaces[0], x, y)
- cr.rectangle(x, y, self._dot_size, self._dot_size)
- cr.fill()
- cr.restore()
- return png_surface
-
- def _new_dot_surface(self, color='#000000', image=None):
- ''' generate a dot of a color color '''
- self._dot_cache = {}
- if image is not None:
- color = COLORS[int(uniform(0, 6))]
- fd = open(os.path.join(self._path, self._PATHS[image]), 'r')
- svg_string = ''
- for line in fd:
- svg_string += line.replace('#000000', color)
- fd.close()
- pixbuf = svg_str_to_pixbuf(svg_string, w=self._dot_size,
- h = self._dot_size)
- '''
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
- os.path.join(self._path, self._PATHS[image]),
- self._dot_size, self._dot_size)
- '''
- else:
- if color in self._dot_cache:
- return self._dot_cache[color]
- self._stroke = color
- self._fill = color
- self._svg_width = self._dot_size
- self._svg_height = self._dot_size
-
- i = self._colors.index(color)
- pixbuf = svg_str_to_pixbuf(
- self._header() + \
- self._circle(self._dot_size / 2., self._dot_size / 2.,
- self._dot_size / 2.) + \
- self._footer())
- surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
- self._svg_width, self._svg_height)
- context = cairo.Context(surface)
- context = gtk.gdk.CairoContext(context)
- context.set_source_pixbuf(pixbuf, 0, 0)
- context.rectangle(0, 0, self._svg_width, self._svg_height)
- context.fill()
- if image is None:
- self._dot_cache[color] = surface
- return surface
-
- def _header(self):
- return '<svg\n' + 'xmlns:svg="http://www.w3.org/2000/svg"\n' + \
- 'xmlns="http://www.w3.org/2000/svg"\n' + \
- 'xmlns:xlink="http://www.w3.org/1999/xlink"\n' + \
- 'version="1.1"\n' + 'width="' + str(self._svg_width) + '"\n' + \
- 'height="' + str(self._svg_height) + '">\n'
-
- def _rect(self, w, h, x, y):
- svg_string = ' <rect\n'
- svg_string += ' width="%f"\n' % (w)
- svg_string += ' height="%f"\n' % (h)
- svg_string += ' rx="%f"\n' % (0)
- svg_string += ' ry="%f"\n' % (0)
- svg_string += ' x="%f"\n' % (x)
- svg_string += ' y="%f"\n' % (y)
- svg_string += 'style="fill:#000000;stroke:#000000;"/>\n'
- return svg_string
-
- def _circle(self, r, cx, cy):
- return '<circle style="fill:' + str(self._fill) + ';stroke:' + \
- str(self._stroke) + ';" r="' + str(r - 0.5) + '" cx="' + \
- str(cx) + '" cy="' + str(cy) + '" />\n'
-
- def _footer(self):
- return '</svg>\n'
-
-
-def svg_str_to_pixbuf(svg_string, w=None, h=None):
- ''' Load pixbuf from SVG string '''
- pl = gtk.gdk.PixbufLoader('svg')
- if w is not None:
- pl.set_size(w, h)
- pl.write(svg_string)
- pl.close()
- return pl.get_pixbuf()
diff --git a/gtk2/grecord.py b/gtk2/grecord.py
deleted file mode 100644
index 02fcbd3..0000000
--- a/gtk2/grecord.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#Copyright (c) 2008, Media Modifications Ltd.
-#Copyright (c) 2011-12, Walter Bender
-
-#Permission is hereby granted, free of charge, to any person obtaining a copy
-#of this software and associated documentation files (the "Software"), to deal
-#in the Software without restriction, including without limitation the rights
-#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-#copies of the Software, and to permit persons to whom the Software is
-#furnished to do so, subject to the following conditions:
-
-#The above copyright notice and this permission notice shall be included in
-#all copies or substantial portions of the Software.
-
-#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-#THE SOFTWARE.
-
-import os
-import time
-
-import gtk
-import gst
-
-import logging
-_logger = logging.getLogger("portfolio-activity")
-
-import gobject
-gobject.threads_init()
-
-
-class Grecord:
-
- def __init__(self, parent):
- self._activity = parent
- self._eos_cb = None
-
- self._can_limit_framerate = False
- self._playing = False
-
- self._audio_transcode_handler = None
- self._transcode_id = None
-
- self._pipeline = gst.Pipeline("Record")
- self._create_audiobin()
-
- bus = self._pipeline.get_bus()
- bus.add_signal_watch()
- bus.connect('message', self._bus_message_handler)
-
- def _create_audiobin(self):
- src = gst.element_factory_make("alsasrc", "absrc")
-
- # attempt to use direct access to the 0,0 device, solving some A/V
- # sync issues
- src.set_property("device", "plughw:0,0")
- hwdev_available = src.set_state(gst.STATE_PAUSED) != \
- gst.STATE_CHANGE_FAILURE
- src.set_state(gst.STATE_NULL)
- if not hwdev_available:
- src.set_property("device", "default")
-
- srccaps = gst.Caps("audio/x-raw-int,rate=16000,channels=1,depth=16")
-
- # Guarantee perfect stream, important for A/V sync
- rate = gst.element_factory_make("audiorate")
-
- # Without a buffer here, gstreamer struggles at the start of the
- # recording and then the A/V sync is bad for the whole video
- # (possibly a gstreamer/ALSA bug -- even if it gets caught up, it
- # should be able to resync without problem).
- queue = gst.element_factory_make("queue", "audioqueue")
- queue.set_property("leaky", True) # prefer fresh data
- queue.set_property("max-size-time", 5000000000) # 5 seconds
- queue.set_property("max-size-buffers", 500)
- queue.connect("overrun", self._log_queue_overrun)
-
- enc = gst.element_factory_make("wavenc", "abenc")
-
- sink = gst.element_factory_make("filesink", "absink")
- sink.set_property("location",
- os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.wav'))
-
- self._audiobin = gst.Bin("audiobin")
- self._audiobin.add(src, rate, queue, enc, sink)
-
- src.link(rate, srccaps)
- gst.element_link_many(rate, queue, enc, sink)
-
- def _log_queue_overrun(self, queue):
- cbuffers = queue.get_property("current-level-buffers")
- cbytes = queue.get_property("current-level-bytes")
- ctime = queue.get_property("current-level-time")
-
- def play(self):
- if self._get_state() == gst.STATE_PLAYING:
- return
-
- self._pipeline.set_state(gst.STATE_PLAYING)
- self._playing = True
-
- def pause(self):
- self._pipeline.set_state(gst.STATE_PAUSED)
- self._playing = False
-
- def stop(self):
- self._pipeline.set_state(gst.STATE_NULL)
- self._playing = False
-
- def is_playing(self):
- return self._playing
-
- def _get_state(self):
- return self._pipeline.get_state()[1]
-
- def stop_recording_audio(self):
- # We should be able to simply pause and remove the audiobin, but
- # this seems to cause a gstreamer segfault. So we stop the whole
- # pipeline while manipulating it.
- # http://dev.laptop.org/ticket/10183
- self._pipeline.set_state(gst.STATE_NULL)
- self._pipeline.remove(self._audiobin)
- self.play()
-
- audio_path = os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.wav')
- if not os.path.exists(audio_path) or os.path.getsize(audio_path) <= 0:
- # FIXME: inform model of failure?
- _logger.error('output.wav does not exist or is empty')
- return
-
- line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! \
-wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! \
-vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! \
-filesink name=audioFilesink'
- self._audioline = gst.parse_launch(line)
-
- vorbis_enc = self._audioline.get_by_name('audioVorbisenc')
-
- audioFilesink = self._audioline.get_by_name('audioFilesink')
- audioOggFilepath = os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.ogg')
- audioFilesink.set_property("location", audioOggFilepath)
-
- audioBus = self._audioline.get_bus()
- audioBus.add_signal_watch()
- self._audio_transcode_handler = audioBus.connect(
- 'message', self._onMuxedAudioMessageCb, self._audioline)
- self._transcode_id = gobject.timeout_add(200, self._transcodeUpdateCb,
- self._audioline)
- self._audiopos = 0
- self._audioline.set_state(gst.STATE_PLAYING)
-
- def transcoding_complete(self):
- # The EOS message is sometimes either not sent or not received.
- # So if the position in the stream is not advancing, assume EOS.
- if self._transcode_id is None:
- _logger.debug('EOS.... transcoding finished')
- return True
- else:
- position, duration = self._query_position(self._audioline)
- # _logger.debug('position: %s, duration: %s' % (str(position),
- # str(duration)))
- if position == duration:
- _logger.debug('We are done, even though we did not see EOS')
- self._clean_up_transcoding_pipeline(self._audioline)
- return True
- elif position == self._audiopos:
- _logger.debug('No progess, so assume we are done')
- self._clean_up_transcoding_pipeline(self._audioline)
- return True
- self._audiopos = position
- return False
-
- def blockedCb(self, x, y, z):
- pass
-
- def record_audio(self):
- # We should be able to add the audiobin on the fly, but unfortunately
- # this results in several seconds of silence being added at the start
- # of the recording. So we stop the whole pipeline while adjusting it.
- # SL#2040
- self._pipeline.set_state(gst.STATE_NULL)
- self._pipeline.add(self._audiobin)
- self.play()
-
- def _transcodeUpdateCb(self, pipe):
- position, duration = self._query_position(pipe)
- if position != gst.CLOCK_TIME_NONE:
- value = position * 100.0 / duration
- value = value / 100.0
- return True
-
- def _query_position(self, pipe):
- try:
- position, format = pipe.query_position(gst.FORMAT_TIME)
- except:
- position = gst.CLOCK_TIME_NONE
-
- try:
- duration, format = pipe.query_duration(gst.FORMAT_TIME)
- except:
- duration = gst.CLOCK_TIME_NONE
-
- return (position, duration)
-
- def _onMuxedAudioMessageCb(self, bus, message, pipe):
- # _logger.debug(message.type)
- if message.type != gst.MESSAGE_EOS:
- return True
- self._clean_up_transcoding_pipeline(pipe)
- return False
-
- def _clean_up_transcoding_pipeline(self, pipe):
- gobject.source_remove(self._audio_transcode_handler)
- self._audio_transcode_handler = None
- gobject.source_remove(self._transcode_id)
- self._transcode_id = None
- pipe.set_state(gst.STATE_NULL)
- pipe.get_bus().remove_signal_watch()
- pipe.get_bus().disable_sync_message_emission()
-
- wavFilepath = os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.wav')
- os.remove(wavFilepath)
- return
-
- def _bus_message_handler(self, bus, message):
- t = message.type
- if t == gst.MESSAGE_EOS:
- if self._eos_cb:
- cb = self._eos_cb
- self._eos_cb = None
- cb()
- elif t == gst.MESSAGE_ERROR:
- # TODO: if we come out of suspend/resume with errors, then
- # get us back up and running... TODO: handle "No space
- # left on the resource.gstfilesink.c" err, debug =
- # message.parse_error()
- pass
diff --git a/gtk2/setup.py b/gtk2/setup.py
deleted file mode 100644
index e5026ee..0000000
--- a/gtk2/setup.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-import os
-import sys
-
-if len(sys.argv) > 1 and '--no-sugar' == sys.argv[1]:
- # Remove the argument from the stack so we don't cause problems
- # for distutils
- sys.argv.pop(1)
-
- import glob, os.path, string
- from distutils.core import setup
-
- DATA_FILES = [
- ('icons', glob.glob('icons/*')),
- ('images', glob.glob('images/*')),
- ('/usr/share/applications', ['turtleart.desktop'])
- ]
-
- setup (name = 'Turtle Art',
- description = "A LOGO-like tool for teaching programming",
- author = "Walter Bender",
- author_email = "walter.bender@gmail.com",
- version = '0.9.4',
- packages = ['TurtleArt'],
- scripts = ['turtleart'],
- data_files = DATA_FILES,
- )
-else:
- from sugar.activity import bundlebuilder
-
- if __name__ == "__main__":
- bundlebuilder.start()
diff --git a/gtk2/sprites.py b/gtk2/sprites.py
deleted file mode 100644
index 2b8bb55..0000000
--- a/gtk2/sprites.py
+++ /dev/null
@@ -1,459 +0,0 @@
-# -*- coding: utf-8 -*-
-
-#Copyright (c) 2007-8, Playful Invention Company.
-#Copyright (c) 2008-11 Walter Bender
-
-#Permission is hereby granted, free of charge, to any person obtaining a copy
-#of this software and associated documentation files (the "Software"), to deal
-#in the Software without restriction, including without limitation the rights
-#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-#copies of the Software, and to permit persons to whom the Software is
-#furnished to do so, subject to the following conditions:
-
-#The above copyright notice and this permission notice shall be included in
-#all copies or substantial portions of the Software.
-
-#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-#THE SOFTWARE.
-
-'''
-
-sprites.py is a simple sprites library for managing graphics objects,
-'sprites', on a gtk.DrawingArea. It manages multiple sprites with
-methods such as move, hide, set_layer, etc.
-
-There are two classes:
-
-class Sprites maintains a collection of sprites
-class Sprite manages individual sprites within the collection.
-
-Example usage:
- # Import the classes into your program.
- from sprites import Sprites Sprite
-
- # Create a new sprite collection associated with your widget
- self.sprite_list = Sprites(widget)
-
- # Create a "pixbuf" (in this example, from SVG).
- my_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>")
-
- # Create a sprite at position x1, y1.
- my_sprite = sprites.Sprite(self.sprite_list, x1, y1, my_pixbuf)
-
- # Move the sprite to a new position.
- my_sprite.move((x1+dx, y1+dy))
-
- # Create another "pixbuf".
- your_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>")
-
- # Create a sprite at position x2, y2.
- your_sprite = sprites.Sprite(self.sprite_list, x2, y2, my_pixbuf)
-
- # Assign the sprites to layers.
- # In this example, your_sprite will be on top of my_sprite.
- my_sprite.set_layer(100)
- your_sprite.set_layer(200)
-
- # Now put my_sprite on top of your_sprite.
- my_sprite.set_layer(300)
-
- cr = self.window.cairo_create()
- # In your activity's do_expose_event, put in a call to redraw_sprites
- self.sprites.redraw_sprites(event.area, cairo_context)
-
-# method for converting SVG to a gtk pixbuf
-def svg_str_to_pixbuf(svg_string):
- pl = gtk.gdk.PixbufLoader('svg')
- pl.write(svg_string)
- pl.close()
- pixbuf = pl.get_pixbuf()
- return pixbuf
-
-'''
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
-import pangocairo
-import cairo
-
-class Sprites:
- ''' A class for the list of sprites and everything they share in common '''
-
- def __init__(self, widget):
- ''' Initialize an empty array of sprites '''
- self.widget = widget
- self.list = []
- self.cr = None
-
- def set_cairo_context(self, cr):
- ''' Cairo context may be set or reset after __init__ '''
- self.cr = cr
-
- def get_sprite(self, i):
- ''' Return a sprint from the array '''
- if i < 0 or i > len(self.list) - 1:
- return(None)
- else:
- return(self.list[i])
-
- def length_of_list(self):
- ''' How many sprites are there? '''
- return(len(self.list))
-
- def append_to_list(self, spr):
- ''' Append a new sprite to the end of the list. '''
- self.list.append(spr)
-
- def insert_in_list(self, spr, i):
- ''' Insert a sprite at position i. '''
- if i < 0:
- self.list.insert(0, spr)
- elif i > len(self.list) - 1:
- self.list.append(spr)
- else:
- self.list.insert(i, spr)
-
- def remove_from_list(self, spr):
- ''' Remove a sprite from the list. '''
- if spr in self.list:
- self.list.remove(spr)
-
- def find_sprite(self, pos, inverse=False):
- ''' Search based on (x, y) position. Return the 'top/first' one. '''
- list = self.list[:]
- if not inverse:
- list.reverse()
- for spr in list:
- if spr.hit(pos):
- return spr
- return None
-
- def redraw_sprites(self, area=None, cr=None):
- ''' Redraw the sprites that intersect area. '''
- # I think I need to do this to save Cairo some work
- if cr is None:
- cr = self.cr
- else:
- self.cr = cr
- if cr is None:
- print 'sprites.redraw_sprites: no Cairo context'
- return
- for spr in self.list:
- if area == None:
- spr.draw(cr=cr)
- else:
- intersection = spr.rect.intersect(area)
- if intersection.width > 0 or intersection.height > 0:
- spr.draw(cr=cr)
-
-
-class Sprite:
- ''' A class for the individual sprites '''
-
- def __init__(self, sprites, x, y, image):
- ''' Initialize an individual sprite '''
- self._sprites = sprites
- self.save_xy = (x, y) # remember initial (x, y) position
- self.rect = gtk.gdk.Rectangle(int(x), int(y), 0, 0)
- self._scale = [12]
- self._rescale = [True]
- self._horiz_align = ["center"]
- self._vert_align = ["middle"]
- self._fd = None
- self._bold = False
- self._italic = False
- self._color = None
- self._margins = [0, 0, 0, 0]
- self.layer = 100
- self.labels = []
- self.cached_surfaces = []
- self._dx = [] # image offsets
- self._dy = []
- self.type = None
- self.set_image(image)
- self._sprites.append_to_list(self)
-
- def set_image(self, image, i=0, dx=0, dy=0):
- ''' Add an image to the sprite. '''
- while len(self.cached_surfaces) < i + 1:
- self.cached_surfaces.append(None)
- self._dx.append(0)
- self._dy.append(0)
- self._dx[i] = dx
- self._dy[i] = dy
- if isinstance(image, gtk.gdk.Pixbuf) or \
- isinstance(image, cairo.ImageSurface):
- w = image.get_width()
- h = image.get_height()
- else:
- w, h = image.get_size()
- if i == 0: # Always reset width and height when base image changes.
- self.rect.width = w + dx
- self.rect.height = h + dy
- else:
- if w + dx > self.rect.width:
- self.rect.width = w + dx
- if h + dy > self.rect.height:
- self.rect.height = h + dy
- if isinstance(image, cairo.ImageSurface):
- self.cached_surfaces[i] = image
- else: # Convert to Cairo surface
- surface = cairo.ImageSurface(
- cairo.FORMAT_ARGB32, self.rect.width, self.rect.height)
- context = cairo.Context(surface)
- context = gtk.gdk.CairoContext(context)
- context.set_source_pixbuf(image, 0, 0)
- context.rectangle(0, 0, self.rect.width, self.rect.height)
- context.fill()
- self.cached_surfaces[i] = surface
-
- def move(self, pos):
- ''' Move to new (x, y) position '''
- self.inval()
- self.rect.x, self.rect.y = int(pos[0]), int(pos[1])
- self.inval()
-
- def move_relative(self, pos):
- ''' Move to new (x+dx, y+dy) position '''
- self.inval()
- self.rect.x += int(pos[0])
- self.rect.y += int(pos[1])
- self.inval()
-
- def get_xy(self):
- ''' Return current (x, y) position '''
- return (self.rect.x, self.rect.y)
-
- def get_dimensions(self):
- ''' Return current size '''
- return (self.rect.width, self.rect.height)
-
- def get_layer(self):
- ''' Return current layer '''
- return self.layer
-
- def set_shape(self, image, i=0):
- ''' Set the current image associated with the sprite '''
- self.inval()
- self.set_image(image, i)
- self.inval()
-
- def set_layer(self, layer=None):
- ''' Set the layer for a sprite '''
- self._sprites.remove_from_list(self)
- if layer is not None:
- self.layer = layer
- for i in range(self._sprites.length_of_list()):
- if layer < self._sprites.get_sprite(i).layer:
- self._sprites.insert_in_list(self, i)
- self.inval()
- return
- self._sprites.append_to_list(self)
- self.inval()
-
- def set_label(self, new_label, i=0):
- ''' Set the label drawn on the sprite '''
- self._extend_labels_array(i)
- if type(new_label) is str or type(new_label) is unicode:
- # pango doesn't like nulls
- self.labels[i] = new_label.replace("\0", " ")
- else:
- self.labels[i] = str(new_label)
- self.inval()
-
- def set_margins(self, l=0, t=0, r=0, b=0):
- ''' Set the margins for drawing the label '''
- self._margins = [l, t, r, b]
-
- def _extend_labels_array(self, i):
- ''' Append to the labels attribute list '''
- if self._fd is None:
- self.set_font('Sans')
- if self._color is None:
- self._color = (0., 0., 0.)
- while len(self.labels) < i + 1:
- self.labels.append(" ")
- self._scale.append(self._scale[0])
- self._rescale.append(self._rescale[0])
- self._horiz_align.append(self._horiz_align[0])
- self._vert_align.append(self._vert_align[0])
-
- def set_font(self, font):
- ''' Set the font for a label '''
- self._fd = pango.FontDescription(font)
-
- def set_label_color(self, rgb):
- ''' Set the font color for a label '''
- COLORTABLE = {'black': '#000000', 'white': '#FFFFFF',
- 'red': '#FF0000', 'yellow': '#FFFF00',
- 'green': '#00FF00', 'cyan': '#00FFFF',
- 'blue': '#0000FF', 'purple': '#FF00FF',
- 'gray': '#808080'}
- if rgb.lower() in COLORTABLE:
- rgb = COLORTABLE[rgb.lower()]
- # Convert from '#RRGGBB' to floats
- self._color = (int('0x' + rgb[1:3], 16) / 256.,
- int('0x' + rgb[3:5], 16) / 256.,
- int('0x' + rgb[5:7], 16) / 256.)
- return
-
- def set_label_attributes(self, scale, rescale=True, horiz_align="center",
- vert_align="middle", i=0):
- ''' Set the various label attributes '''
- self._extend_labels_array(i)
- self._scale[i] = scale
- self._rescale[i] = rescale
- self._horiz_align[i] = horiz_align
- self._vert_align[i] = vert_align
-
- def hide(self):
- ''' Hide a sprite '''
- self.inval()
- self._sprites.remove_from_list(self)
-
- def restore(self):
- ''' Restore a hidden sprite '''
- self.set_layer()
-
- def inval(self):
- ''' Invalidate a region for gtk '''
- self._sprites.widget.queue_draw_area(self.rect.x,
- self.rect.y,
- self.rect.width,
- self.rect.height)
-
- def draw(self, cr=None):
- ''' Draw the sprite (and label) '''
- if cr is None:
- print 'sprite.draw: no Cairo context.'
- return
- for i, surface in enumerate(self.cached_surfaces):
- cr.set_source_surface(surface,
- self.rect.x + self._dx[i],
- self.rect.y + self._dy[i])
- cr.rectangle(self.rect.x + self._dx[i],
- self.rect.y + self._dy[i],
- self.rect.width,
- self.rect.height)
- cr.fill()
- if len(self.labels) > 0:
- self.draw_label(cr)
-
- def hit(self, pos):
- ''' Is (x, y) on top of the sprite? '''
- x, y = pos
- if x < self.rect.x:
- return False
- if x > self.rect.x + self.rect.width:
- return False
- if y < self.rect.y:
- return False
- if y > self.rect.y + self.rect.height:
- return False
- return True
-
- def draw_label(self, cr):
- ''' Draw the label based on its attributes '''
- # Create a pangocairo context
- cr = pangocairo.CairoContext(cr)
- my_width = self.rect.width - self._margins[0] - self._margins[2]
- if my_width < 0:
- my_width = 0
- my_height = self.rect.height - self._margins[1] - self._margins[3]
- for i in range(len(self.labels)):
- pl = cr.create_layout()
- pl.set_text(str(self.labels[i]))
- self._fd.set_size(int(self._scale[i] * pango.SCALE))
- pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
- if w > my_width:
- if self._rescale[i]:
- self._fd.set_size(
- int(self._scale[i] * pango.SCALE * my_width / w))
- pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
- else:
- j = len(self.labels[i]) - 1
- while(w > my_width and j > 0):
- pl.set_text(
- "…" + self.labels[i][len(self.labels[i]) - j:])
- self._fd.set_size(int(self._scale[i] * pango.SCALE))
- pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
- j -= 1
- if self._horiz_align[i] == "center":
- x = int(self.rect.x + self._margins[0] + (my_width - w) / 2)
- elif self._horiz_align[i] == 'left':
- x = int(self.rect.x + self._margins[0])
- else: # right
- x = int(self.rect.x + self.rect.width - w - self._margins[2])
- h = pl.get_size()[1] / pango.SCALE
- if self._vert_align[i] == "middle":
- y = int(self.rect.y + self._margins[1] + (my_height - h) / 2)
- elif self._vert_align[i] == "top":
- y = int(self.rect.y + self._margins[1])
- else: # bottom
- y = int(self.rect.y + self.rect.height - h - self._margins[3])
- cr.save()
- cr.translate(x, y)
- cr.set_source_rgb(self._color[0], self._color[1], self._color[2])
- cr.update_layout(pl)
- cr.show_layout(pl)
- cr.restore()
-
- def label_width(self):
- ''' Calculate the width of a label '''
- cr = pangocairo.CairoContext(self._sprites.cr)
- if cr is not None:
- max = 0
- for i in range(len(self.labels)):
- pl = cr.create_layout()
- pl.set_text(self.labels[i])
- self._fd.set_size(int(self._scale[i] * pango.SCALE))
- pl.set_font_description(self._fd)
- w = pl.get_size()[0] / pango.SCALE
- if w > max:
- max = w
- return max
- else:
- return self.rect.width
-
- def label_safe_width(self):
- ''' Return maximum width for a label '''
- return self.rect.width - self._margins[0] - self._margins[2]
-
- def label_safe_height(self):
- ''' Return maximum height for a label '''
- return self.rect.height - self._margins[1] - self._margins[3]
-
- def label_left_top(self):
- ''' Return the upper-left corner of the label safe zone '''
- return(self._margins[0], self._margins[1])
-
- def get_pixel(self, pos, i=0):
- ''' Return the pixel at (x, y) '''
- x = int(pos[0] - self.rect.x)
- y = int(pos[1] - self.rect.y)
- if x < 0 or x > (self.rect.width - 1) or \
- y < 0 or y > (self.rect.height - 1):
- return(-1, -1, -1, -1)
-
- # create a new 1x1 cairo surface
- cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1);
- cr = cairo.Context(cs)
- cr.set_source_surface(self.cached_surfaces[i], -x, -y)
- cr.rectangle(0,0,1,1)
- cr.set_operator(cairo.OPERATOR_SOURCE)
- cr.fill()
- cs.flush() # ensure all writing is done
- # Read the pixel
- pixels = cs.get_data()
- return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0)
-
diff --git a/gtk2/toolbar_utils.py b/gtk2/toolbar_utils.py
deleted file mode 100644
index 94e6883..0000000
--- a/gtk2/toolbar_utils.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2011, 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
-
-from sugar.graphics.radiotoolbutton import RadioToolButton
-from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.combobox import ComboBox
-from sugar.graphics.toolcombobox import ToolComboBox
-
-
-def combo_factory(combo_array, toolbar, callback, cb_arg=None,
- tooltip=None, default=None):
- '''Factory for making a toolbar combo box'''
- combo = ComboBox()
- if tooltip is not None and hasattr(combo, 'set_tooltip_text'):
- combo.set_tooltip_text(tooltip)
- if cb_arg is not None:
- combo.connect('changed', callback, cb_arg)
- else:
- combo.connect('changed', callback)
- for i, selection in enumerate(combo_array):
- combo.append_item(i, selection, None)
- combo.show()
- toolitem = gtk.ToolItem()
- toolitem.add(combo)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- if default is not None:
- combo.set_active(combo_array.index(default))
- return combo
-
-
-def entry_factory(default_string, toolbar, tooltip=None, max=3):
- ''' Factory for adding a text box to a toolbar '''
- entry = gtk.Entry()
- entry.set_text(default_string)
- if tooltip is not None and hasattr(entry, 'set_tooltip_text'):
- entry.set_tooltip_text(tooltip)
- entry.set_width_chars(max)
- entry.show()
- toolitem = gtk.ToolItem()
- toolitem.add(entry)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return entry
-
-
-def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None,
- accelerator=None):
- '''Factory for making tooplbar buttons'''
- button = ToolButton(icon_name)
- if tooltip is not None:
- button.set_tooltip(tooltip)
- button.props.sensitive = True
- if accelerator is not None:
- button.props.accelerator = accelerator
- if cb_arg is not None:
- button.connect('clicked', callback, cb_arg)
- else:
- button.connect('clicked', callback)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(button, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(button, -1)
- button.show()
- return button
-
-
-def radio_factory(name, toolbar, callback, cb_arg=None, tooltip=None,
- group=None):
- ''' Add a radio button to a toolbar '''
- button = RadioToolButton(group=group)
- button.set_named_icon(name)
- if callback is not None:
- if cb_arg is None:
- button.connect('clicked', callback)
- else:
- button.connect('clicked', callback, cb_arg)
- if hasattr(toolbar, 'insert'): # Add button to the main toolbar...
- toolbar.insert(button, -1)
- else: # ...or a secondary toolbar.
- toolbar.props.page.insert(button, -1)
- button.show()
- if tooltip is not None:
- button.set_tooltip(tooltip)
- return button
-
-
-def label_factory(toolbar, label_text, width=None):
- ''' Factory for adding a label to a toolbar '''
- label = gtk.Label(label_text)
- label.set_line_wrap(True)
- if width is not None:
- label.set_size_request(width, -1) # doesn't work on XOs
- label.show()
- toolitem = gtk.ToolItem()
- toolitem.add(label)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return label
-
-
-def separator_factory(toolbar, expand=False, visible=True):
- ''' add a separator to a toolbar '''
- separator = gtk.SeparatorToolItem()
- separator.props.draw = visible
- separator.set_expand(expand)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(separator, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(separator, -1)
- separator.show()
-
-
-def image_factory(image, toolbar, tooltip=None):
- ''' Add an image to the toolbar '''
- img = gtk.Image()
- img.set_from_pixbuf(image)
- img_tool = gtk.ToolItem()
- img_tool.add(img)
- if tooltip is not None:
- img.set_tooltip_text(tooltip)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(img_tool, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(img_tool, -1)
- img_tool.show()
- return img
-
-
-def spin_factory(default, min, max, callback, toolbar):
- spin_adj = gtk.Adjustment(default, min, max, 1, 32, 0)
- spin = gtk.SpinButton(spin_adj, 0, 0)
- spin_id = spin.connect('value-changed', callback)
- spin.set_numeric(True)
- spin.show()
- toolitem = gtk.ToolItem()
- toolitem.add(spin)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else:
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return spin
diff --git a/gtk2/toolbar_utils.py~ b/gtk2/toolbar_utils.py~
deleted file mode 100644
index ef2382d..0000000
--- a/gtk2/toolbar_utils.py~
+++ /dev/null
@@ -1,165 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2011, Walter Bender
-# Port To GTK3:
-# Ignacio Rodriguez <ignaciorodriguez@sugarlabs.org>
-# 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
-
-
-from gi.repository import Gtk
-
-from sugar3.graphics.radiotoolbutton import RadioToolButton
-from sugar3.graphics.toolbutton import ToolButton
-from sugar3.graphics.combobox import ComboBox
-from sugar3.graphics.toolcombobox import ToolComboBox
-
-
-def combo_factory(combo_array, toolbar, callback, cb_arg=None,
- tooltip=None, default=None):
- '''Factory for making a toolbar combo box'''
- combo = ComboBox()
- if tooltip is not None and hasattr(combo, 'set_tooltip_text'):
- combo.set_tooltip_text(tooltip)
- if cb_arg is not None:
- combo.connect('changed', callback, cb_arg)
- else:
- combo.connect('changed', callback)
- for i, selection in enumerate(combo_array):
- combo.append_item(i, selection, None)
- combo.show()
- toolitem = Gtk.ToolItem()
- toolitem.add(combo)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- if default is not None:
- combo.set_active(combo_array.index(default))
- return combo
-
-
-def entry_factory(default_string, toolbar, tooltip=None, max=3):
- ''' Factory for adding a text box to a toolbar '''
- entry = Gtk.Entry()
- entry.set_text(default_string)
- if tooltip is not None and hasattr(entry, 'set_tooltip_text'):
- entry.set_tooltip_text(tooltip)
- entry.set_width_chars(max)
- entry.show()
- toolitem = Gtk.ToolItem()
- toolitem.add(entry)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return entry
-
-
-def button_factory(icon_name, toolbar, callback, cb_arg=None, tooltip=None,
- accelerator=None):
- '''Factory for making tooplbar buttons'''
- button = ToolButton(icon_name)
- if tooltip is not None:
- button.set_tooltip(tooltip)
- button.props.sensitive = True
- if accelerator is not None:
- button.props.accelerator = accelerator
- if cb_arg is not None:
- button.connect('clicked', callback, cb_arg)
- else:
- button.connect('clicked', callback)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(button, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(button, -1)
- button.show()
- return button
-
-
-def radio_factory(name, toolbar, callback, cb_arg=None, tooltip=None,
- group=None):
- ''' Add a radio button to a toolbar '''
- button = RadioToolButton(group=group)
- button.set_named_icon(name)
- if callback is not None:
- if cb_arg is None:
- button.connect('clicked', callback)
- else:
- button.connect('clicked', callback, cb_arg)
- if hasattr(toolbar, 'insert'): # Add button to the main toolbar...
- toolbar.insert(button, -1)
- else: # ...or a secondary toolbar.
- toolbar.props.page.insert(button, -1)
- button.show()
- if tooltip is not None:
- button.set_tooltip(tooltip)
- return button
-
-
-def label_factory(toolbar, label_text, width=None):
- ''' Factory for adding a label to a toolbar '''
- label = Gtk.Label(label_text)
- label.set_line_wrap(True)
- if width is not None:
- label.set_size_request(width, -1) # doesn't work on XOs
- label.show()
- toolitem = Gtk.ToolItem()
- toolitem.add(label)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return label
-
-
-def separator_factory(toolbar, expand=False, visible=True):
- ''' add a separator to a toolbar '''
- separator = Gtk.SeparatorToolItem()
- separator.props.draw = visible
- separator.set_expand(expand)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(separator, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(separator, -1)
- separator.show()
-
-
-def image_factory(image, toolbar, tooltip=None):
- ''' Add an image to the toolbar '''
- img = Gtk.Image()
- img.set_from_pixbuf(image)
- img_tool = Gtk.ToolItem()
- img_tool.add(img)
- if tooltip is not None:
- img.set_tooltip_text(tooltip)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(img_tool, -1)
- else: # or a secondary toolbar
- toolbar.props.page.insert(img_tool, -1)
- img_tool.show()
- return img
-
-
-def spin_factory(default, min, max, callback, toolbar):
- spin_adj = Gtk.Adjustment(default, min, max, 1, 32, 0)
- spin = Gtk.SpinButton(spin_adj, 0, 0)
- spin_id = spin.connect('value-changed', callback)
- spin.set_numeric(True)
- spin.show()
- toolitem = Gtk.ToolItem()
- toolitem.add(spin)
- if hasattr(toolbar, 'insert'): # the main toolbar
- toolbar.insert(toolitem, -1)
- else:
- toolbar.props.page.insert(toolitem, -1)
- toolitem.show()
- return spin
diff --git a/gtk2/utils.py b/gtk2/utils.py
deleted file mode 100644
index 230ab45..0000000
--- a/gtk2/utils.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#Copyright (c) 2011 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 subprocess
-from StringIO import StringIO
-try:
- OLD_SUGAR_SYSTEM = False
- import json
- json.dumps
- from json import load as jload
- from json import dump as jdump
-except (ImportError, AttributeError):
- try:
- import simplejson as json
- from simplejson import load as jload
- from simplejson import dump as jdump
- except:
- OLD_SUGAR_SYSTEM = True
-
-
-def json_load(text):
- """ Load JSON data using what ever resources are available. """
- if OLD_SUGAR_SYSTEM is True:
- listdata = json.read(text)
- else:
- # strip out leading and trailing whitespace, nulls, and newlines
- io = StringIO(text)
- try:
- listdata = jload(io)
- except ValueError:
- # assume that text is ascii list
- listdata = text.split()
- for i, value in enumerate(listdata):
- listdata[i] = int(value)
- return listdata
-
-
-def json_dump(data):
- """ Save data using available JSON tools. """
- if OLD_SUGAR_SYSTEM is True:
- return json.write(data)
- else:
- _io = StringIO()
- jdump(data, _io)
- return _io.getvalue()
-
-
-def play_audio_from_file(file_path):
- """ Audio media """
- command_line = ['gst-launch', 'filesrc', 'location=' + file_path,
- '! oggdemux', '! vorbisdec', '! audioconvert',
- '! alsasink']
- subprocess.call(command_line)