Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xactivity.py79
-rw-r--r--library/pippy/__init__.py6
-rw-r--r--library/pippy/console.py65
-rw-r--r--library/pippy/game.py32
-rwxr-xr-xlibrary/pippy/sound.py251
-rw-r--r--pippy_app.py182
6 files changed, 404 insertions, 211 deletions
diff --git a/activity.py b/activity.py
index 276818c..0b0ddae 100755
--- a/activity.py
+++ b/activity.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-# Copyright (C) 2007,2008 One Laptop per Child Association, Inc.
+# Copyright (C) 2007,2008,2010 One Laptop per Child Association, Inc.
# Written by C. Scott Ananian <cscott@laptop.org>
#
# This program is free software; you can redistribute it and/or modify
@@ -19,25 +19,29 @@
"""Pippy activity helper classes."""
from sugar.activity import activity
+
class ViewSourceActivity(activity.Activity):
"""Activity subclass which handles the 'view source' key."""
def __init__(self, handle, **kwargs):
super(ViewSourceActivity, self).__init__(handle, **kwargs)
- self.__source_object_id = None # XXX: persist this across invocations?
+ self.__source_object_id = None # XXX: persist this across invocations?
self.connect('key-press-event', self._key_press_cb)
+
def _key_press_cb(self, widget, event):
import gtk
if gtk.gdk.keyval_name(event.keyval) == 'XF86Start':
self.view_source()
return True
return False
+
def view_source(self):
"""Implement the 'view source' key by saving pippy_app.py to the
datastore, and then telling the Journal to view it."""
if self.__source_object_id is None:
from sugar import profile
from sugar.datastore import datastore
- from sugar.activity.activity import get_bundle_name, get_bundle_path
+ from sugar.activity.activity \
+ import get_bundle_name, get_bundle_path
from gettext import gettext as _
import os.path
jobject = datastore.create()
@@ -48,13 +52,14 @@ class ViewSourceActivity(activity.Activity):
'icon-color': profile.get_color().to_string(),
'mime_type': 'text/x-python',
}
- for k,v in metadata.items():
- jobject.metadata[k] = v # dict.update method is missing =(
+ for k, v in metadata.items():
+ jobject.metadata[k] = v # dict.update method is missing =(
jobject.file_path = os.path.join(get_bundle_path(), 'pippy_app.py')
datastore.write(jobject)
self.__source_object_id = jobject.object_id
jobject.destroy()
self.journal_show_object(self.__source_object_id)
+
def journal_show_object(self, object_id):
"""Invoke journal_show_object from sugar.activity.activity if it
exists."""
@@ -62,13 +67,17 @@ class ViewSourceActivity(activity.Activity):
from sugar.activity.activity import show_object_in_journal
show_object_in_journal(object_id)
except ImportError:
- pass # no love from sugar.
+ pass # no love from sugar.
TARGET_TYPE_TEXT = 80
+
+
class VteActivity(ViewSourceActivity):
"""Activity subclass built around the Vte terminal widget."""
def __init__(self, handle):
- import gtk, pango, vte
+ import gtk
+ import pango
+ import vte
from sugar.graphics.toolbutton import ToolButton
from gettext import gettext as _
super(VteActivity, self).__init__(handle)
@@ -90,16 +99,16 @@ class VteActivity(ViewSourceActivity):
# creates vte widget
self._vte = vte.Terminal()
- self._vte.set_size(30,5)
+ self._vte.set_size(30, 5)
self._vte.set_size_request(200, 300)
font = 'Monospace 10'
self._vte.set_font(pango.FontDescription(font))
- self._vte.set_colors(gtk.gdk.color_parse ('#000000'),
- gtk.gdk.color_parse ('#E7E7E7'),
+ self._vte.set_colors(gtk.gdk.color_parse('#000000'),
+ gtk.gdk.color_parse('#E7E7E7'),
[])
self._vte.connect('selection-changed', self._on_selection_changed_cb)
self._vte.drag_dest_set(gtk.DEST_DEFAULT_ALL,
- [ ( "text/plain", 0, TARGET_TYPE_TEXT ) ],
+ [("text/plain", 0, TARGET_TYPE_TEXT)],
gtk.gdk.ACTION_COPY)
self._vte.connect('drag_data_received', self._on_drop_cb)
# ...and its scrollbar
@@ -111,7 +120,7 @@ class VteActivity(ViewSourceActivity):
self.set_canvas(vtebox)
self.show_all()
# hide the buttons we don't use.
- toolbar.share.hide() # this should share bundle.
+ toolbar.share.hide() # this should share bundle.
toolbar.keep.hide()
edittoolbar.undo.hide()
edittoolbar.redo.hide()
@@ -123,44 +132,54 @@ class VteActivity(ViewSourceActivity):
bundle_path = activity.get_bundle_path()
# the 'sleep 1' works around a bug with the command dying before
# the vte widget manages to snarf the last bits of its output
- self._pid = self._vte.fork_command \
- (command='/bin/sh',
- argv=['/bin/sh','-c',
- 'python %s/pippy_app.py; sleep 1' % bundle_path],
- envv=["PYTHONPATH=%s/library" % bundle_path],
- directory=bundle_path)
+ self._pid = self._vte.fork_command(
+ command='/bin/sh',
+ argv=['/bin/sh', '-c',
+ 'python %s/pippy_app.py; sleep 1' % bundle_path],
+ envv=["PYTHONPATH=%s/library" % bundle_path],
+ directory=bundle_path)
+
def _on_copy_clicked_cb(self, widget):
if self._vte.get_has_selection():
self._vte.copy_clipboard()
+
def _on_paste_clicked_cb(self, widget):
self._vte.paste_clipboard()
+
def _on_selection_changed_cb(self, widget):
self._copy_button.set_sensitive(self._vte.get_has_selection())
+
def _on_drop_cb(self, widget, context, x, y, selection, targetType, time):
if targetType == TARGET_TYPE_TEXT:
self._vte.feed_child(selection.data)
+
def on_child_exit(self, widget):
"""This method is invoked when the user's script exits."""
- pass # override in subclass
+ pass # override in subclass
+
class PyGameActivity(ViewSourceActivity):
"""Activity wrapper for a pygame."""
def __init__(self, handle):
# fork pygame before we initialize the activity.
- import os, pygame, sys
+ import os
+ import pygame
+ import sys
pygame.init()
windowid = pygame.display.get_wm_info()['wmwindow']
self.child_pid = os.fork()
if self.child_pid == 0:
- library_path = os.path.join(activity.get_bundle_path(), 'library')
- pippy_app_path = os.path.join(activity.get_bundle_path(), 'pippy_app.py')
- sys.path[0:0] = [ library_path ]
+ bp = activity.get_bundle_path()
+ library_path = os.path.join(bp, 'library')
+ pippy_app_path = os.path.join(bp, 'pippy_app.py')
+ sys.path[0:0] = [library_path]
g = globals()
- g['__name__']='__main__'
- execfile(pippy_app_path, g, g) # start pygame
+ g['__name__'] = '__main__'
+ execfile(pippy_app_path, g, g) # start pygame
sys.exit(0)
super(PyGameActivity, self).__init__(handle)
- import gobject, gtk, os
+ import gobject
+ import gtk
toolbox = activity.ActivityToolbox(self)
toolbar = toolbox.get_activity_toolbar()
self.set_toolbox(toolbox)
@@ -174,15 +193,16 @@ class PyGameActivity(ViewSourceActivity):
socket.grab_focus()
gobject.child_watch_add(self.child_pid, lambda pid, cond: self.close())
# hide the buttons we don't use.
- toolbar.share.hide() # this should share bundle.
+ toolbar.share.hide() # this should share bundle.
toolbar.keep.hide()
+
def _main():
"""Launch this activity from the command line."""
from sugar.activity import activityfactory
from sugar.activity.registry import ActivityInfo
from sugar.bundle.activitybundle import ActivityBundle
- import os, os.path
+ import os
ab = ActivityBundle(os.path.dirname(__file__) or '.')
ai = ActivityInfo(name=ab.get_name(),
icon=None,
@@ -198,4 +218,5 @@ def _main():
cmd_args = activityfactory.get_command(ai)
os.execvpe(cmd_args[0], cmd_args, env)
-if __name__=='__main__': _main()
+if __name__ == '__main__':
+ _main()
diff --git a/library/pippy/__init__.py b/library/pippy/__init__.py
index 98d48d7..e5c88f1 100644
--- a/library/pippy/__init__.py
+++ b/library/pippy/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2007,2008 One Laptop per Child Association, Inc.
+# Copyright (C) 2007,2008,2010 One Laptop per Child Association, Inc.
#
# 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
@@ -17,12 +17,12 @@
"""Pippy standard library."""
import pippy.console as console
import pippy.game as pygame
-#import pippy.physics as physics
try:
import pippy.sound as sound
except ImportError:
- pass # this module fails to import on non-XOs.
+ pass # this module fails to import on non-XOs.
+
def wait(delay=0.1):
"""Pause briefly, for animations."""
diff --git a/library/pippy/console.py b/library/pippy/console.py
index 7dbd73f..e36725f 100644
--- a/library/pippy/console.py
+++ b/library/pippy/console.py
@@ -1,5 +1,5 @@
"""Console helpers for pippy."""
-# Copyright (C) 2007,2008 One Laptop per Child Association, Inc.
+# Copyright (C) 2007,2008,2010 One Laptop per Child Association, Inc.
# Written by C. Scott Ananian <cscott@laptop.org>
#
# This program is free software; you can redistribute it and/or modify
@@ -16,27 +16,34 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import sys
+import os
+import tty
+import termios
+
+
def clear():
"""Clear screen on console."""
# magic escape sequence
sys.stdout.write('\x1B[H\x1B[J')
+
def size():
"""Return the number of rows/columns in the current terminal widget."""
# xterm magic! see http://rtfm.etla.org/xterm/ctlseq.html
- import os, tty, termios
- fd = os.open('/dev/tty', os.O_RDWR|os.O_APPEND)
+ fd = os.open('/dev/tty', os.O_RDWR | os.O_APPEND)
+
def read_to_delimit(delimit):
buf = []
while True:
c = os.read(fd, 1)
- if c==delimit: break
+ if c == delimit:
+ break
buf.append(c)
return ''.join(buf)
- oldattr = termios.tcgetattr(fd) # make sure we can restore tty state
- tty.setraw(fd, termios.TCSANOW) # set to raw mode.
- os.write(fd, '\x1B[18t') # write the 'query screen size' command
- read_to_delimit('\x1b') # parse response.
+ oldattr = termios.tcgetattr(fd) # make sure we can restore tty state
+ tty.setraw(fd, termios.TCSANOW) # set to raw mode.
+ os.write(fd, '\x1B[18t') # write the 'query screen size' command
+ read_to_delimit('\x1b') # parse response.
read_to_delimit('[')
size = read_to_delimit('t')
# Output can be '8;rows;cols' or 'rows;cols' depending on vte version.
@@ -48,34 +55,37 @@ def size():
else:
rows = int(values[0])
cols = int(values[1])
- termios.tcsetattr(fd, termios.TCSANOW, oldattr) # reset tty
+ termios.tcsetattr(fd, termios.TCSANOW, oldattr) # reset tty
return cols, rows
+
def getpos():
"""Return the current x, y position of the cursor on the screen.
The top-left corner is 1,1."""
# xterm magic! see http://rtfm.etla.org/xterm/ctlseq.html
- sys.stdout.flush() # ensure that writes to the terminal have finished
- import os, tty, termios
- fd = os.open('/dev/tty', os.O_RDWR|os.O_APPEND)
+ sys.stdout.flush() # ensure that writes to the terminal have finished
+ fd = os.open('/dev/tty', os.O_RDWR | os.O_APPEND)
+
def read_to_delimit(delimit):
buf = []
while True:
c = os.read(fd, 1)
- if c==delimit: break
+ if c == delimit:
+ break
buf.append(c)
return ''.join(buf)
- oldattr = termios.tcgetattr(fd) # make sure we can restore tty state
- tty.setraw(fd, termios.TCSANOW) # set to raw mode.
- os.write(fd, '\x1B[6n') # Report Cursor Position
- read_to_delimit('\x1b') # parse response.
+ oldattr = termios.tcgetattr(fd) # make sure we can restore tty state
+ tty.setraw(fd, termios.TCSANOW) # set to raw mode.
+ os.write(fd, '\x1B[6n') # Report Cursor Position
+ read_to_delimit('\x1b') # parse response.
read_to_delimit('[')
row = int(read_to_delimit(';'))
col = int(read_to_delimit('R'))
- termios.tcsetattr(fd, termios.TCSANOW, oldattr) # reset tty
+ termios.tcsetattr(fd, termios.TCSANOW, oldattr) # reset tty
return col, row
+
def setpos(column, row):
"""Move to the given position on the screen.
@@ -83,86 +93,105 @@ def setpos(column, row):
# xterm magic! see http://rtfm.etla.org/xterm/ctlseq.html
sys.stdout.write('\x1B[%d;%dH' % (row, column))
+
def up(count=1):
"""Move the cursor up the given number of rows."""
sys.stdout.write('\x1B[%dA' % count)
+
def down(count=1):
"""Move the cursor down the given number of rows."""
sys.stdout.write('\x1B[%dB' % count)
+
def forward(count=1):
"""Move the cursor forward the given number of columns."""
sys.stdout.write('\x1B[%dC' % count)
+
def backward(count=1):
"""Move the cursor backward the given number of columns."""
sys.stdout.write('\x1B[%dD' % count)
+
def normal():
"""Switch to normal text."""
sys.stdout.write('\x1B[0m')
+
def bold():
"""Switch to bold text."""
sys.stdout.write('\x1B[1m')
+
def underlined():
"""Switch to underlined text."""
sys.stdout.write('\x1B[4m')
+
def inverse():
"""Switch to inverse text."""
sys.stdout.write('\x1B[7m')
+
def black():
"""Change text color to black."""
# magic escape sequence.
sys.stdout.write('\x1B[30m')
+
def red():
"""Change text color to red."""
# magic escape sequence.
sys.stdout.write('\x1B[31m')
+
def green():
"""Change text color to green."""
# magic escape sequence.
sys.stdout.write('\x1B[32m')
+
def yellow():
"""Change text color to yellow."""
# magic escape sequence.
sys.stdout.write('\x1B[33m')
+
def blue():
"""Change text color to blue."""
# magic escape sequence.
sys.stdout.write('\x1B[34m')
+
def magenta():
"""Change text color to magenta."""
# magic escape sequence.
sys.stdout.write('\x1B[35m')
+
def cyan():
"""Change text color to cyan."""
# magic escape sequence.
sys.stdout.write('\x1B[36m')
+
def white():
"""Change text color to white."""
# magic escape sequence.
sys.stdout.write('\x1B[37m')
+
def hide_cursor():
"""Hide the cursor."""
sys.stdout.write('\x1B[?25l')
+
def show_cursor():
"""Show the cursor."""
sys.stdout.write('\x1B[?25h')
+
def reset():
"""Clear screen and reset text color."""
clear()
diff --git a/library/pippy/game.py b/library/pippy/game.py
index 09dcd74..f047a6f 100644
--- a/library/pippy/game.py
+++ b/library/pippy/game.py
@@ -16,6 +16,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
def pause():
"""Display a "Paused" screen and suspend."""
from gettext import gettext as _
@@ -25,19 +26,19 @@ def pause():
old_screen = screen.copy() # save this for later.
# dim the screen and display the 'paused' message in the center.
- BLACK = (0,0,0)
- WHITE = (255,255,255)
+ BLACK = (0, 0, 0)
+ WHITE = (255, 255, 255)
dimmed = screen.copy()
dimmed.set_alpha(128)
screen.fill(BLACK)
- screen.blit(dimmed, (0,0))
- font = pygame.font.Font(None, 36) # 36px high
+ screen.blit(dimmed, (0, 0))
+ font = pygame.font.Font(None, 36) # 36px high
msg = _("PAUSED")
msg_surf = font.render(msg, True, BLACK, WHITE)
+
def center(rect, screen):
- rect.center = (screen.get_width()/2, screen.get_height()/2)
-
- rect = pygame.Rect((0,0),msg_surf.get_size())
+ rect.center = (screen.get_width() / 2, screen.get_height() / 2)
+ rect = pygame.Rect((0, 0), msg_surf.get_size())
rect.inflate_ip(rect.width, rect.height)
center(rect, screen)
screen.fill(WHITE, rect)
@@ -48,17 +49,19 @@ def pause():
# SUSPEND
try:
- raise RuntimeError() # XXX don't try this yet. we should use ohm.
- open('/sys/power/state','w').write('mem')
- except: # couldn't suspend (no permissions?)
+ raise RuntimeError() # XXX don't try this yet. we should use ohm.
+ open('/sys/power/state', 'w').write('mem')
+ except: # couldn't suspend (no permissions?)
pygame.event.post(pygame.event.wait())
pygame.display.set_caption(caption, icon_caption)
- screen.blit(old_screen, (0,0))
+ screen.blit(old_screen, (0, 0))
pygame.display.flip()
-_last_event_time=0
-_default_clock=None
+_last_event_time = 0
+_default_clock = None
+
+
def next_frame(max_fps=20, idle_timeout=20, clock=None, pause=pause):
"""Limit maximum frame rate of pygame. Returns True.
@@ -76,9 +79,8 @@ def next_frame(max_fps=20, idle_timeout=20, clock=None, pause=pause):
if pygame.event.peek(xrange(pygame.NOEVENT, pygame.USEREVENT)):
# we're not idle anymore.
_last_event_time = pygame.time.get_ticks()
- elif (pygame.time.get_ticks() - _last_event_time) >= idle_timeout*1000:
+ elif (pygame.time.get_ticks() - _last_event_time) >= idle_timeout * 1000:
# we've been idle for a long time. Pause & suspend.
pause()
_last_event_time = pygame.time.get_ticks()
-
return True
diff --git a/library/pippy/sound.py b/library/pippy/sound.py
index d0c78b5..c5f864d 100755
--- a/library/pippy/sound.py
+++ b/library/pippy/sound.py
@@ -14,7 +14,6 @@
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
import os
import sys
from gettext import gettext as _
@@ -29,18 +28,21 @@ fnum = [100]
"""XXX: This function seems to be broken. (CSA)
def quit(self):
perf.Stop()
- perf.Join()
+ perf.Join()
cs.Reset()
- cs = None
+ cs = None
"""
+
def finddir():
for d in dirs:
if os.path.isdir(d):
return d
+
def defAdsr(attack=0.01, decay=0.1, sustain=0.8, release=0.1):
- """Define an ADSR envelope. fnum = defADSR(attack = [0.01], decay = [0.1], sustain = [0.8], release = [0.1])"""
+ """ Define an ADSR envelope. fnum = defADSR(attack = [0.01],
+ decay = [0.1], sustain = [0.8], release = [0.1]) """
att = int(2048 * attack)
dec = int(2048 * decay)
rel = int(2048 * release)
@@ -48,11 +50,15 @@ def defAdsr(attack=0.01, decay=0.1, sustain=0.8, release=0.1):
sus = min(1., sustain)
fnum[0] += 1
- scorelines.append("f%ld 0 2048 7 0 %ld 1. %ld %f %ld %f %ld 0\n" % (fnum[0], att, dec, sus, bal, sus, rel))
+ scorelines.append("f%ld 0 2048 7 0 %ld 1. %ld %f %ld %f %ld 0\n" %
+ (fnum[0], att, dec, sus, bal, sus, rel))
return fnum[0]
-def defLineSegments(list=[0,10,1,10,0,10,1,10,0]):
- """Define a breakpoints envelope. list=[0,10,1,10,0,10,1,10,0]. list begin with the start value of the function and is follow by any pair values (duration, value). The number of elements in the list should odd."""
+
+def defLineSegments(list=[0, 10, 1, 10, 0, 10, 1, 10, 0]):
+ """ Define a breakpoints envelope. list begin with the start
+ value of the function and is follow by any pair values (duration,
+ value). The number of elements in the list should be odd. """
totalLength = 0
newlist = []
@@ -61,44 +67,79 @@ def defLineSegments(list=[0,10,1,10,0,10,1,10,0]):
totalLength += list[i]
for i in range(len(list)):
- if (i % 2) == 0: newlist.append(list[i])
- else: newlist.append(int(2048 * (list[i] / float(totalLength))))
+ if (i % 2) == 0:
+ newlist.append(list[i])
+ else:
+ newlist.append(int(2048 * (list[i] / float(totalLength))))
fnum[0] += 1
- scorelines.append("f" + str(fnum[0]) + " 0 2048 -7 " + " ".join([str(n) for n in newlist]) + '\n')
+ scorelines.append("f" + str(fnum[0]) + " 0 2048 -7 " +
+ " ".join([str(n) for n in newlist]) + '\n')
return fnum[0]
-def defComplexWave(list=[1,0,0,.3,0,.2,0,0,.1]):
- """Define a complex waveform to be read with 'playComplex' function. list=[1,0,0,.3,0,.2,0,0,.1]
-is a list of amplitude for succesive harmonics of a waveform"""
+
+def defComplexWave(list=[1, 0, 0, .3, 0, .2, 0, 0, .1]):
+ """ Define a complex waveform to be read with 'playComplex'
+ function. list=[1, 0, 0, .3, 0, .2, 0, 0, .1] is a list of
+ amplitude for succesive harmonics of a waveform """
fnum[0] += 1
- scorelines.append("f" + str(fnum[0]) + " 0 2048 10 " + " ".join([str(n) for n in list]) + '\n')
+ scorelines.append("f" + str(fnum[0]) + " 0 2048 10 " +
+ " ".join([str(n) for n in list]) + '\n')
return fnum[0]
-def playSine( pitch=1000, amplitude=5000, duration=1, starttime=0, pitch_envelope='default', amplitude_envelope='default'):
- """Play a sine wave (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0], pitch_envelope=['default'], amplitude_envelope=['default'])"""
- _play(pitch, amplitude, duration, starttime, pitch_envelope, amplitude_envelope, 1)
-
-def playSquare( pitch=1000, amplitude=5000, duration=1, starttime=0, pitch_envelope='default', amplitude_envelope='default'):
- """Play a square wave (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0], pitch_envelope=['default'], amplitude_envelope=['default'])"""
- _play(pitch, amplitude, duration, starttime, pitch_envelope, amplitude_envelope, 2)
-def playSawtooth( pitch=1000, amplitude=5000, duration=1, starttime=0, pitch_envelope='default', amplitude_envelope='default'):
- """Play a sawtooth wave (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0], pitch_envelope=['default'], amplitude_envelope=['default'])"""
- _play(pitch, amplitude, duration, starttime, pitch_envelope, amplitude_envelope, 3)
+def playSine(pitch=1000, amplitude=5000, duration=1, starttime=0,
+ pitch_envelope='default', amplitude_envelope='default'):
+ """ Play a sine wave
+ (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0],
+ pitch_envelope=['default'], amplitude_envelope=['default']) """
+ _play(pitch, amplitude, duration, starttime, pitch_envelope,
+ amplitude_envelope, 1)
+
+
+def playSquare(pitch=1000, amplitude=5000, duration=1, starttime=0,
+ pitch_envelope='default', amplitude_envelope='default'):
+ """ Play a square wave
+ (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0],
+ pitch_envelope=['default'], amplitude_envelope=['default']) """
+ _play(pitch, amplitude, duration, starttime, pitch_envelope,
+ amplitude_envelope, 2)
+
+
+def playSawtooth(pitch=1000, amplitude=5000, duration=1, starttime=0,
+ pitch_envelope='default', amplitude_envelope='default'):
+ """ Play a sawtooth wave (pitch = [1000], amplitude = [5000],
+ duration = [1], starttime = [0], pitch_envelope=['default'],
+ amplitude_envelope=['default']) """
+ _play(pitch, amplitude, duration, starttime, pitch_envelope,
+ amplitude_envelope, 3)
+
+
+def playComplex(pitch=1000, amplitude=5000, duration=1, starttime=0,
+ pitch_envelope='default', amplitude_envelope='default',
+ wave='default'):
+ """ Play a complex wave
+ (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0],
+ pitch_envelope = ['default'], amplitude_envelope, wave = ['default'] ) """
+ if wave == 'default':
+ wavetable = 10
+ else:
+ wavetable = wave
+ _play(pitch, amplitude, duration, starttime, pitch_envelope,
+ amplitude_envelope, wavetable)
-def playComplex( pitch=1000, amplitude=5000, duration=1, starttime=0, pitch_envelope='default', amplitude_envelope='default', wave='default'):
- """Play a complex wave (pitch = [1000], amplitude = [5000], duration = [1], starttime = [0], pitch_envelope = ['default'], amplitude_envelope, wave = ['default'] )"""
- if wave == 'default': wavetable = 10
- else: wavetable = wave
- _play(pitch, amplitude, duration, starttime, pitch_envelope, amplitude_envelope, wavetable)
-def _play( pitch, amplitude, duration, starttime, pitch_envelope, amplitude_envelope, instrument):
- if pitch_envelope == 'default': pitenv = 99
- else: pitenv = pitch_envelope
+def _play(pitch, amplitude, duration, starttime, pitch_envelope,
+ amplitude_envelope, instrument):
+ if pitch_envelope == 'default':
+ pitenv = 99
+ else:
+ pitenv = pitch_envelope
- if amplitude_envelope == 'default': ampenv = 100
- else: ampenv = amplitude_envelope
+ if amplitude_envelope == 'default':
+ ampenv = 100
+ else:
+ ampenv = amplitude_envelope
if not 1 in instrlist:
orchlines.append("instr 1\n")
@@ -109,27 +150,54 @@ def _play( pitch, amplitude, duration, starttime, pitch_envelope, amplitude_enve
orchlines.append("endin\n\n")
instrlist.append(1)
- scorelines.append("i1 %s %s %s %s %s %s %s\n" % (str(starttime), str(duration), str(pitch), str(amplitude), str(pitenv), str(ampenv), str(instrument)))
-
-def playFrequencyModulation( pitch=500, amplitude=5000, duration=2, starttime=0, carrier=1, modulator=.5, index=5, pitch_envelope='default', amplitude_envelope='default', carrier_envelope='default', modulator_envelope='default', index_envelope='default', wave='default'):
- """Play a frequency modulation synthesis sound (pitch = [100], amplitude = [5000], duration = [2], starttime = [0], carrier = [1], modulator = [.5], index = [5], pitch_envelope = ['default'], amplitude_envelope = ['default'], carrier_envelope = ['default'], modulator_envelope = ['default'], index_envelope = ['default'], wave = ['default'] )"""
- if pitch_envelope == 'default': pitenv = 99
- else: pitenv = pitch_envelope
+ scorelines.append("i1 %s %s %s %s %s %s %s\n" %
+ (str(starttime), str(duration), str(pitch),
+ str(amplitude), str(pitenv), str(ampenv),
+ str(instrument)))
+
+
+def playFrequencyModulation(pitch=500, amplitude=5000, duration=2, starttime=0,
+ carrier=1, modulator=.5, index=5,
+ pitch_envelope='default',
+ amplitude_envelope='default',
+ carrier_envelope='default',
+ modulator_envelope='default',
+ index_envelope='default', wave='default'):
+ """ Play a frequency modulation synthesis sound (pitch = [100],
+ amplitude = [5000], duration = [2], starttime = [0], carrier =
+ [1], modulator = [.5], index = [5], pitch_envelope = ['default'],
+ amplitude_envelope = ['default'], carrier_envelope = ['default'],
+ modulator_envelope = ['default'], index_envelope = ['default'],
+ wave = ['default'] ) """
+ if pitch_envelope == 'default':
+ pitenv = 99
+ else:
+ pitenv = pitch_envelope
- if amplitude_envelope == 'default': ampenv = 100
- else: ampenv = amplitude_envelope
+ if amplitude_envelope == 'default':
+ ampenv = 100
+ else:
+ ampenv = amplitude_envelope
- if carrier_envelope == 'default': carenv = 99
- else: carenv = carrier_envelope
+ if carrier_envelope == 'default':
+ carenv = 99
+ else:
+ carenv = carrier_envelope
- if modulator_envelope == 'default': modenv = 99
- else: modenv = modulator_envelope
+ if modulator_envelope == 'default':
+ modenv = 99
+ else:
+ modenv = modulator_envelope
- if index_envelope == 'default': indenv = 99
- else: indenv = index_envelope
+ if index_envelope == 'default':
+ indenv = 99
+ else:
+ indenv = index_envelope
- if wave == 'default': wavetable = 1
- else: wavetable = wave
+ if wave == 'default':
+ wavetable = 1
+ else:
+ wavetable = wave
if not 7 in instrlist:
orchlines.append("instr 7\n")
@@ -138,20 +206,33 @@ def playFrequencyModulation( pitch=500, amplitude=5000, duration=2, starttime=0,
orchlines.append("kcarenv oscil 1, 1/p3, p12\n")
orchlines.append("kmodenv oscil 1, 1/p3, p13\n")
orchlines.append("kindenv oscil 1, 1/p3, p14\n")
- orchlines.append("asig foscil p5*kenv, p4*kpitenv, p6*kcarenv, p7*kmodenv, p8*kindenv, p9\n")
+ orchlines.append("asig foscil p5*kenv, p4*kpitenv, p6*kcarenv, "
+ "p7*kmodenv, p8*kindenv, p9\n")
orchlines.append("out asig\n")
orchlines.append("endin\n\n")
instrlist.append(7)
- scorelines.append("i7 %s %s %s %s %s %s %s %s %s %s %s %s %s\n" % (str(starttime), str(duration), str(pitch), str(amplitude), str(carrier), str(modulator), str(index), str(wavetable), str(pitenv), str(ampenv), str(carenv), str(modenv), str(indenv)))
+ scorelines.append("i7 %s %s %s %s %s %s %s %s %s %s %s %s %s\n" %
+ (str(starttime), str(duration), str(pitch),
+ str(amplitude), str(carrier), str(modulator),
+ str(index), str(wavetable), str(pitenv), str(ampenv),
+ str(carenv), str(modenv), str(indenv)))
-def playPluck( pitch=100, amplitude=5000, duration=2, starttime=0, pitch_envelope='default', amplitude_envelope='default'):
- """Play a string physical modeling sound (pitch = [100], amplitude = [5000], duration = [2], starttime = [0], pitch_envelope = ['default'], amplitude_envelope )"""
- if pitch_envelope == 'default': pitenv = 99
- else: pitenv = pitch_envelope
- if amplitude_envelope == 'default': ampenv = 100
- else: ampenv = amplitude_envelope
+def playPluck(pitch=100, amplitude=5000, duration=2, starttime=0,
+ pitch_envelope='default', amplitude_envelope='default'):
+ """ Play a string physical modeling sound (pitch = [100],
+ amplitude = [5000], duration = [2], starttime = [0],
+ pitch_envelope = ['default'], amplitude_envelope ) """
+ if pitch_envelope == 'default':
+ pitenv = 99
+ else:
+ pitenv = pitch_envelope
+
+ if amplitude_envelope == 'default':
+ ampenv = 100
+ else:
+ ampenv = amplitude_envelope
if not 8 in instrlist:
orchlines.append("instr 8\n")
@@ -163,35 +244,51 @@ def playPluck( pitch=100, amplitude=5000, duration=2, starttime=0, pitch_envelop
orchlines.append("endin\n\n")
instrlist.append(8)
- scorelines.append("i8 %s %s %s %s %s %s\n" % (str(starttime), str(duration), str(pitch), str(amplitude), str(pitenv), str(ampenv)))
+ scorelines.append("i8 %s %s %s %s %s %s\n" %
+ (str(starttime), str(duration), str(pitch),
+ str(amplitude), str(pitenv), str(ampenv)))
+
-def playWave(sound='horse', pitch=1, amplitude=1, loop=False, duration=1, starttime=0, pitch_envelope='default', amplitude_envelope='default'):
- """Play a wave file (sound = ['horse'], pitch = [1], amplitude = [1], loop = [False], duration = [1], starttime = [0], pitch_envelope=['default'], amplitude_envelope=['default'])"""
+def playWave(sound='horse', pitch=1, amplitude=1, loop=False, duration=1,
+ starttime=0, pitch_envelope='default',
+ amplitude_envelope='default'):
+ """ Play a wave file (sound = ['horse'], pitch = [1], amplitude =
+ [1], loop = [False], duration = [1], starttime = [0],
+ pitch_envelope=['default'], amplitude_envelope=['default']) """
if '/' in sound:
fullname = sound
else:
fullname = finddir() + str(sound)
- if loop == False: lp = 0
- else: lp = 1
+ if loop == False:
+ lp = 0
+ else:
+ lp = 1
- if pitch_envelope == 'default': pitenv = 99
- else: pitenv = pitch_envelope
+ if pitch_envelope == 'default':
+ pitenv = 99
+ else:
+ pitenv = pitch_envelope
- if amplitude_envelope == 'default': ampenv = 100
- else: ampenv = amplitude_envelope
+ if amplitude_envelope == 'default':
+ ampenv = 100
+ else:
+ ampenv = amplitude_envelope
if not 9 in instrlist:
- orchlines.append("instr 9\n")
+ orchlines.append("instr 9\n")
orchlines.append("kpitenv oscil 1, 1/p3, p8\n")
orchlines.append("aenv oscil 1, 1/p3, p9\n")
- orchlines.append("asig diskin p4, p5*kpitenv, 0, p7\n")
+ orchlines.append("asig diskin p4, p5*kpitenv, 0, p7\n")
orchlines.append("out asig*p6*aenv\n")
orchlines.append("endin\n\n")
instrlist.append(9)
- scorelines.append('i9 %f %f "%s" %s %s %s %s %s\n' % (float(starttime), float(duration), fullname, str(pitch), str(amplitude), str(lp), str(pitenv), str(ampenv)))
-
+ scorelines.append('i9 %f %f "%s" %s %s %s %s %s\n' %
+ (float(starttime), float(duration), fullname, str(pitch),
+ str(amplitude), str(lp), str(pitenv), str(ampenv)))
+
+
def getSoundList():
list = finddir()
if list == None:
@@ -199,14 +296,16 @@ def getSoundList():
sys.exit(0)
return sorted(os.listdir(list))
-temp_path=None
+temp_path = None
+
+
def audioOut(file=None):
- """Compile a .csd file and start csound to run it. If a string is given as argument, it write a wave file on disk instead of sending sound to hp. (file = [None])"""
+ """ Compile a .csd file and start csound to run it. If a string is
+ given as argument, it write a wave file on disk instead of sending
+ sound to hp. (file = [None]) """
global temp_path
- import os
if temp_path is None:
from sugar import env
- import os.path
temp_path = env.get_profile_path() + '/pippy'
if not os.path.isdir(temp_path):
os.mkdir(temp_path)
@@ -240,5 +339,5 @@ def audioOut(file=None):
csd.write("\n</CsScore>\n")
csd.write("\n</CsoundSynthesizer>")
csd.close()
-
+
os.system('csound ' + path + '/temp.csd >/dev/null 2>/dev/null')
diff --git a/pippy_app.py b/pippy_app.py
index 2e46cf5..980d18a 100644
--- a/pippy_app.py
+++ b/pippy_app.py
@@ -1,6 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-# Copyright (C) 2007,2008,2009 Chris Ball, based on Collabora's "hellomesh" demo.
+# Copyright (C) 2007,2008,2009 Chris Ball, based on Collabora's
+# "hellomesh" demo.
#
# 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
@@ -22,7 +23,8 @@ import gtk
import logging
import pango
import vte
-import re, os, os.path
+import re
+import os
import gobject
import time
@@ -42,7 +44,7 @@ import groupthink.gtk_tools
text_buffer = None
# magic prefix to use utf-8 source encoding
-PYTHON_PREFIX="""#!/usr/bin/python
+PYTHON_PREFIX = """#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
@@ -59,6 +61,7 @@ SIZE_Y = gtk.gdk.screen_height()
groupthink_mimetype = 'pickle/groupthink-pippy'
+
class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
"""Pippy Activity as specified in activity.info"""
def early_setup(self):
@@ -82,12 +85,16 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
from sugar.graphics.menuitem import MenuItem
from sugar.graphics.icon import Icon
menu_item = MenuItem(_('As Pippy Document'))
- menu_item.set_image(Icon(file=('%s/activity/activity-icon.svg' % get_bundle_path()), icon_size=gtk.ICON_SIZE_MENU))
+ menu_item.set_image(Icon(file=('%s/activity/activity-icon.svg' %
+ get_bundle_path()),
+ icon_size=gtk.ICON_SIZE_MENU))
menu_item.connect('activate', self.keepbutton_cb)
palette.menu.append(menu_item)
menu_item.show()
menu_item = MenuItem(_('As Activity Bundle'))
- menu_item.set_image(Icon(file=('%s/activity/activity-default.svg' % get_bundle_path()), icon_size=gtk.ICON_SIZE_MENU))
+ menu_item.set_image(Icon(file=('%s/activity/activity-default.svg' %
+ get_bundle_path()),
+ icon_size=gtk.ICON_SIZE_MENU))
menu_item.connect('activate', self.makebutton_cb)
palette.menu.append(menu_item)
menu_item.show()
@@ -127,8 +134,8 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
gobutton.props.accelerator = _('<alt>r')
gobutton.set_icon_widget(goicon_bw)
gobutton.set_tooltip("Run")
- gobutton.connect('clicked', self.flash_cb, dict({'bw':goicon_bw,
- 'color':goicon_color}))
+ gobutton.connect('clicked', self.flash_cb, dict({'bw': goicon_bw,
+ 'color': goicon_color}))
gobutton.connect('clicked', self.gobutton_cb)
actions_toolbar.insert(gobutton, -1)
@@ -140,8 +147,8 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
stopbutton = ToolButton(label=_("_Stop"))
stopbutton.props.accelerator = _('<alt>s')
stopbutton.set_icon_widget(stopicon_bw)
- stopbutton.connect('clicked', self.flash_cb, dict({'bw':stopicon_bw,
- 'color':stopicon_color}))
+ stopbutton.connect('clicked', self.flash_cb, dict({'bw': stopicon_bw,
+ 'color': stopicon_color}))
stopbutton.connect('clicked', self.stopbutton_cb)
stopbutton.set_tooltip("Stop Running")
actions_toolbar.insert(stopbutton, -1)
@@ -150,13 +157,14 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
clearicon_bw = gtk.Image()
clearicon_bw.set_from_file("%s/icons/eraser_bw.svg" % os.getcwd())
clearicon_color = gtk.Image()
- clearicon_color.set_from_file("%s/icons/eraser_color.svg" % os.getcwd())
+ clearicon_color.set_from_file("%s/icons/eraser_color.svg" %
+ os.getcwd())
clearbutton = ToolButton(label=_("_Clear"))
clearbutton.props.accelerator = _('<alt>c')
clearbutton.set_icon_widget(clearicon_bw)
clearbutton.connect('clicked', self.clearbutton_cb)
- clearbutton.connect('clicked', self.flash_cb, dict({'bw':clearicon_bw,
- 'color':clearicon_color}))
+ clearbutton.connect('clicked', self.flash_cb, dict({'bw': clearicon_bw,
+ 'color': clearicon_color}))
clearbutton.set_tooltip("Clear")
actions_toolbar.insert(clearbutton, -1)
@@ -194,17 +202,19 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
root = os.path.join(get_bundle_path(), 'data')
for d in sorted(os.listdir(root)):
- if not os.path.isdir(os.path.join(root,d)): continue #skip non-dirs
- direntry = { "name": _(d.capitalize()),
- "path": os.path.join(root,d) + "/" }
+ if not os.path.isdir(os.path.join(root, d)):
+ continue # skip non-dirs
+ direntry = {"name": _(d.capitalize()),
+ "path": os.path.join(root, d) + "/"}
olditer = self.model.insert_before(None, None)
self.model.set_value(olditer, 0, direntry)
self.model.set_value(olditer, 1, direntry["name"])
for _file in sorted(os.listdir(os.path.join(root, d))):
- if _file.endswith('~'): continue # skip emacs backups
- entry = { "name": _(_file.capitalize()),
- "path": os.path.join(root, d, _file) }
+ if _file.endswith('~'):
+ continue # skip emacs backups
+ entry = {"name": _(_file.capitalize()),
+ "path": os.path.join(root, d, _file)}
_iter = self.model.insert_before(olditer, None)
self.model.set_value(_iter, 0, entry)
self.model.set_value(_iter, 1, entry["name"])
@@ -219,13 +229,14 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
langs = lang_manager.list_languages()
else:
lang_ids = lang_manager.get_language_ids()
- langs = [lang_manager.get_language(lang_id) for lang_id in lang_ids]
+ langs = [lang_manager.get_language(lang_id)
+ for lang_id in lang_ids]
for lang in langs:
for m in lang.get_mime_types():
if m == "text/x-python":
text_buffer.set_language(lang)
- if hasattr(text_buffer,'set_highlight'):
+ if hasattr(text_buffer, 'set_highlight'):
text_buffer.set_highlight(True)
else:
text_buffer.set_highlight_syntax(True)
@@ -263,13 +274,13 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
self._vte.set_size(30, 5)
font = 'Monospace ' + str(font_zoom(style.FONT_SIZE))
self._vte.set_font(pango.FontDescription(font))
- self._vte.set_colors(gtk.gdk.color_parse ('#000000'),
- gtk.gdk.color_parse ('#E7E7E7'),
+ self._vte.set_colors(gtk.gdk.color_parse('#000000'),
+ gtk.gdk.color_parse('#E7E7E7'),
[])
self._vte.connect('child_exited', self.child_exited_cb)
self._child_exited_handler = None
self._vte.drag_dest_set(gtk.DEST_DEFAULT_ALL,
- [ ( "text/plain", 0, TARGET_TYPE_TEXT ) ],
+ [("text/plain", 0, TARGET_TYPE_TEXT)],
gtk.gdk.ACTION_COPY)
self._vte.connect('drag_data_received', self.vte_drop_cb)
outbox.pack_start(self._vte)
@@ -284,7 +295,8 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
def when_shared(self):
self.hpane.remove(self.hpane.get_child1())
global text_buffer
- self.cloud.sharefield = groupthink.gtk_tools.TextBufferSharePoint(text_buffer)
+ self.cloud.sharefield = \
+ groupthink.gtk_tools.TextBufferSharePoint(text_buffer)
# HACK : There are issues with undo/redoing while in shared
# mode. So disable the 'undo' and 'redo' buttons when the activity
# is shared.
@@ -294,10 +306,11 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
def vte_drop_cb(self, widget, context, x, y, selection, targetType, time):
if targetType == TARGET_TYPE_TEXT:
self._vte.feed_child(selection.data)
+
def selection_cb(self, column):
self.save()
model, _iter = column.get_selected()
- value = model.get_value(_iter,0)
+ value = model.get_value(_iter, 0)
self._logger.debug("clicked! %s" % value['path'])
_file = open(value['path'], 'r')
lines = _file.readlines()
@@ -339,6 +352,7 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
f.write(PYTHON_PREFIX)
for line in text:
f.write(line)
+
def _reset_vte(self):
self._vte.grab_focus()
self._vte.feed("\x1B[H\x1B[J\x1B[0;39m")
@@ -361,10 +375,9 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
global text_buffer
text_buffer.paste_clipboard(gtk.Clipboard(), None, True)
-
def gobutton_cb(self, button):
from shutil import copy2
- self.stopbutton_cb(button) # try stopping old code first.
+ self.stopbutton_cb(button) # try stopping old code first.
self._reset_vte()
# FIXME: We're losing an odd race here
@@ -376,18 +389,19 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
copy2('%s/activity.py' % get_bundle_path(),
'%s/tmp/activity.py' % self.get_activity_root())
- self._pid = self._vte.fork_command \
- (command="/bin/sh",
- argv=["/bin/sh", "-c",
- "python %s; sleep 1" % pippy_app_name],
- envv=["PYTHONPATH=%s/library:%s" % (get_bundle_path(), os.getenv("PYTHONPATH", ""))],
- directory=get_bundle_path())
+ self._pid = self._vte.fork_command(
+ command="/bin/sh",
+ argv=["/bin/sh", "-c",
+ "python %s; sleep 1" % pippy_app_name],
+ envv=["PYTHONPATH=%s/library:%s" % (get_bundle_path(),
+ os.getenv("PYTHONPATH", ""))],
+ directory=get_bundle_path())
def stopbutton_cb(self, button):
try:
os.kill(self._pid, SIGTERM)
except:
- pass # process must already be dead.
+ pass # process must already be dead.
def keepbutton_cb(self, __):
self.copy()
@@ -401,18 +415,19 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
from sugar.graphics.alert import Alert
from sugar.graphics.icon import Icon
alert = Alert()
- alert.props.title =_ ('Save as Activity Error')
- alert.props.msg = _('Please give your activity a meaningful name before attempting to save it as an activity.')
+ alert.props.title = _('Save as Activity Error')
+ alert.props.msg = _('Please give your activity a meaningful name '
+ 'before attempting to save it as an activity.')
ok_icon = Icon(icon_name='dialog-ok')
alert.add_button(gtk.RESPONSE_OK, _('Ok'), ok_icon)
alert.connect('response', self.dismiss_alert_cb)
self.add_alert(alert)
return
- self.stopbutton_cb(None) # try stopping old code first.
+ self.stopbutton_cb(None) # try stopping old code first.
self._reset_vte()
self._vte.feed(_("Creating activity bundle..."))
self._vte.feed("\r\n")
- TMPDIR='instance' # XXX: should be 'tmp', once trac #1731 is fixed.
+ TMPDIR = 'instance' # XXX: should be 'tmp', once trac #1731 is fixed.
app_temp = mkdtemp('.activity', 'Pippy',
os.path.join(self.get_activity_root(), TMPDIR))
sourcefile = os.path.join(app_temp, 'xyzzy.py')
@@ -423,24 +438,26 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
# hook up a callback for when the bundle builder is done.
# we can't use gobject.child_watch_add because vte will reap our
# children before we can.
- self._child_exited_handler = lambda: self.bundle_cb(title, app_temp)
+ self._child_exited_handler = \
+ lambda: self.bundle_cb(title, app_temp)
# invoke bundle builder
- self._pid = self._vte.fork_command \
- (command="/usr/bin/python",
- argv=["/usr/bin/python",
- "%s/pippy_app.py" % get_bundle_path(),
- '-p', '%s/library' % get_bundle_path(),
- '-d', app_temp,
- title, sourcefile],
- directory=app_temp)
+ self._pid = self._vte.fork_command(
+ command="/usr/bin/python",
+ argv=["/usr/bin/python",
+ "%s/pippy_app.py" % get_bundle_path(),
+ '-p', '%s/library' % get_bundle_path(),
+ '-d', app_temp,
+ title, sourcefile],
+ directory=app_temp)
except:
- rmtree(app_temp, ignore_errors=True) # clean up!
+ rmtree(app_temp, ignore_errors=True) # clean up!
raise
def child_exited_cb(self, *args):
"""Called whenever a child exits. If there's a handler, run it."""
h, self._child_exited_handler = self._child_exited_handler, None
- if h is not None: h()
+ if h is not None:
+ h()
def bundle_cb(self, title, app_temp):
"""Called when we're done building a bundle for a source file."""
@@ -449,10 +466,12 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
from sugar.datastore import datastore
try:
# find the .xo file: were we successful?
- bundle_file=[ f for f in os.listdir(app_temp) if f.endswith('.xo') ]
+ bundle_file = [f for f in os.listdir(app_temp) \
+ if f.endswith('.xo')]
if len(bundle_file) != 1:
- self._logger.debug("Couldn't find bundle: %s"%str(bundle_file))
- return # something went wrong.
+ self._logger.debug("Couldn't find bundle: %s" %
+ str(bundle_file))
+ return # something went wrong.
# hand off to journal
os.chmod(app_temp, 0755)
jobject = datastore.create()
@@ -465,7 +484,7 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
'mime_type': 'application/vnd.olpc-sugar',
}
for k, v in metadata.items():
- jobject.metadata[k] = v # the dict.update method is missing =(
+ jobject.metadata[k] = v # the dict.update method is missing =(
jobject.file_path = os.path.join(app_temp, bundle_file[0])
datastore.write(jobject)
self._vte.feed("\r\n")
@@ -474,7 +493,7 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
self.journal_show_object(jobject.object_id)
jobject.destroy()
finally:
- rmtree(app_temp, ignore_errors=True) # clean up!
+ rmtree(app_temp, ignore_errors=True) # clean up!
def dismiss_alert_cb(self, alert, response_id):
self.remove_alert(alert)
@@ -494,7 +513,8 @@ class PippyActivity(ViewSourceActivity, groupthink.sugar_tools.GroupActivity):
def load_from_journal(self, file_path):
if self.metadata['mime_type'] == 'text/x-python':
text = open(file_path).read()
- # discard the '#!/usr/bin/python' and 'coding: utf-8' lines, if present
+ # discard the '#!/usr/bin/python' and 'coding: utf-8' lines,
+ # if present
text = re.sub(r'^' + re.escape(PYTHON_PREFIX), '', text)
global text_buffer
text_buffer.set_text(text)
@@ -564,38 +584,53 @@ PIPPY_DEFAULT_ICON = \
############# ACTIVITY META-INFORMATION ###############
# this is used by Pippy to generate a bundle for itself.
+
def pippy_activity_version():
"""Returns the version number of the generated activity bundle."""
return 38
+
+
def pippy_activity_extra_files():
"""Returns a map of 'extra' files which should be included in the
generated activity bundle."""
# Cheat here and generate the map from the fs contents.
extra = {}
bp = get_bundle_path()
- for d in ['po', 'data', 'groupthink', 'post' ]: # everybody gets library already
+ for d in ['po', 'data', 'groupthink', 'post']: # everybody gets library
for root, dirs, files in os.walk(os.path.join(bp, d)):
for name in files:
- fn = os.path.join(root, name).replace(bp+'/', '')
+ fn = os.path.join(root, name).replace(bp + '/', '')
extra[fn] = open(os.path.join(root, name), 'r').read()
extra['activity/activity-default.svg'] = PIPPY_DEFAULT_ICON
return extra
+
+
def pippy_activity_news():
"""Return the NEWS file for this activity."""
# Cheat again.
return open(os.path.join(get_bundle_path(), 'NEWS')).read()
+
+
def pippy_activity_icon():
"""Return an SVG document specifying the icon for this activity."""
return PIPPY_ICON
+
+
def pippy_activity_class():
"""Return the class which should be started to run this activity."""
return 'pippy_app.PippyActivity'
+
+
def pippy_activity_bundle_id():
"""Return the bundle_id for the generated activity."""
return 'org.laptop.Pippy'
+
+
def pippy_activity_mime_types():
"""Return the mime types handled by the generated activity, as a list."""
return ['text/x-python', groupthink_mimetype]
+
+
def pippy_activity_extra_info():
return """
license = GPLv2+
@@ -603,6 +638,7 @@ update_url = http://wiki.laptop.org/go/Activities/G1G1"""
################# ACTIVITY BUNDLER ################
+
def main():
"""Create a bundle from a pippy-style source file"""
from optparse import OptionParser
@@ -613,7 +649,7 @@ def main():
from sugar.activity import bundlebuilder
import sys
parser = OptionParser(usage='%prog [options] [title] [sourcefile]')
- parser.add_option('-d', '--dir', dest='dir',default='.',metavar='DIR',
+ parser.add_option('-d', '--dir', dest='dir', default='.', metavar='DIR',
help='Put generated bundle in the specified directory.')
parser.add_option('-p', '--pythonpath', dest='path', action='append',
default=[], metavar='DIR',
@@ -625,11 +661,12 @@ def main():
sourcefile = args[1]
pytitle = re.sub(r'[^A-Za-z0-9_]', '', title)
if re.match(r'[0-9]', pytitle) is not None:
- pytitle = '_' + pytitle # first character cannot be numeric
+ pytitle = '_' + pytitle # first character cannot be numeric
# first take a gander at the source file and see if it's got extra info
# for us.
sourcedir, basename = os.path.split(sourcefile)
- if not sourcedir: sourcedir = '.'
+ if not sourcedir:
+ sourcedir = '.'
module, ext = os.path.splitext(basename)
# things we look for:
bundle_info = {
@@ -644,14 +681,15 @@ def main():
}
# are any of these things in the module?
try_import = False
- info = readmodule_ex(module, [ sourcedir ] + options.path)
+ info = readmodule_ex(module, [sourcedir] + options.path)
for func in bundle_info.keys():
p_a_func = 'pippy_activity_%s' % func
- if p_a_func in info: try_import = True
+ if p_a_func in info:
+ try_import = True
if try_import:
# yes, let's try to execute them to get better info about our bundle
oldpath = list(sys.path)
- sys.path[0:0] = [ sourcedir ] + options.path
+ sys.path[0:0] = [sourcedir] + options.path
modobj = __import__(module)
for func in bundle_info.keys():
p_a_func = 'pippy_activity_%s' % func
@@ -661,7 +699,7 @@ def main():
# okay! We've done the hard part. Now let's build a bundle.
# create a new temp dir in which to create the bundle.
- app_temp = mkdtemp('.activity', 'Pippy') # hope TMPDIR is set correctly!
+ app_temp = mkdtemp('.activity', 'Pippy') # hope TMPDIR is set correctly!
bundle = get_bundle_path()
try:
copytree('%s/library' % bundle, '%s/library' % app_temp)
@@ -681,7 +719,8 @@ def main():
assert '..' not in path
dirname, filename = os.path.split(path)
dirname = os.path.join(app_temp, dirname)
- if not os.path.exists(dirname): os.makedirs(dirname)
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
with open(os.path.join(dirname, filename), 'w') as f:
f.write(contents)
# put script into $app_temp/pippy_app.py
@@ -690,14 +729,16 @@ def main():
with open('%s/MANIFEST' % app_temp, 'w') as f:
for dirpath, dirnames, filenames in sorted(os.walk(app_temp)):
for name in sorted(filenames):
- fn = os.path.join(dirpath, name).replace(app_temp+'/', '')
- if fn=='MANIFEST': continue
+ fn = os.path.join(dirpath, name)
+ fn = fn.replace(app_temp + '/', '')
+ if fn == 'MANIFEST':
+ continue
f.write('%s\n' % fn)
# invoke bundle builder
olddir = os.getcwd()
oldargv = sys.argv
os.chdir(app_temp)
- sys.argv = [ 'setup.py', 'dist_xo' ]
+ sys.argv = ['setup.py', 'dist_xo']
bundlebuilder.start()
sys.argv = oldargv
os.chdir(olddir)
@@ -710,8 +751,9 @@ def main():
if __name__ == '__main__':
from gettext import gettext as _
import sys
- if False: # change this to True to test within Pippy
- sys.argv = sys.argv + [ '-d','/tmp','Pippy', '/home/olpc/pippy_app.py' ]
+ if False: # change this to True to test within Pippy
+ sys.argv = sys.argv + ['-d', '/tmp', 'Pippy',
+ '/home/olpc/pippy_app.py']
#print _("Working..."),
#sys.stdout.flush()
main()