Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2011-02-18 13:16:28 (GMT)
committer Walter Bender <walter.bender@gmail.com>2011-02-18 13:16:28 (GMT)
commit0373970d57b2d56530d79b5af8cb97ab39e8e0b7 (patch)
treec59edd8c76ceab91b5d1540c9bb27a73fd56f7b4 /TurtleArt
parent17b5303975703d82a6b02966f017b5b882e1a2c8 (diff)
added plugin mechanisms, camera plugin
Diffstat (limited to 'TurtleArt')
-rw-r--r--TurtleArt/taconstants.py12
-rw-r--r--TurtleArt/talogo.py99
-rw-r--r--TurtleArt/tawindow.py72
3 files changed, 80 insertions, 103 deletions
diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py
index f842719..54fc099 100644
--- a/TurtleArt/taconstants.py
+++ b/TurtleArt/taconstants.py
@@ -224,8 +224,8 @@ BOX_STYLE = ['number', 'xcor', 'ycor', 'heading', 'pensize', 'color', 'shade',
'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple', 'white',
'black', 'titlex', 'titley', 'leftx', 'topy', 'rightx', 'bottomy',
'sound', 'volume', 'pitch', 'voltage', 'resistance', 'gray', 'see', 'rfid',
- 'luminance', 'time']
-BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video', 'camera']
+ 'time']
+BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video']
NUMBER_STYLE = ['plus2', 'product2', 'myfunc']
NUMBER_STYLE_VAR_ARG = ['myfunc1arg', 'myfunc2arg', 'myfunc3arg']
NUMBER_STYLE_BLOCK = ['random']
@@ -279,7 +279,7 @@ OLD_DOCK = ['and', 'or', 'plus', 'minus', 'division', 'product', 'remainder']
# Blocks that contain media
#
CONTENT_BLOCKS = ['number', 'string', 'description', 'audio', 'video',
- 'journal', 'camera']
+ 'journal']
#
# These blocks get a special skin
@@ -315,7 +315,6 @@ BLOCK_NAMES = {
'box': [_('box')],
'box1': [_('box 1')],
'box2': [_('box 2')],
- 'camera': [' '],
'cartesian': [_('Cartesian')],
'clean': [_(' clean ')],
'clearheap': [_('empty heap')],
@@ -355,7 +354,6 @@ BLOCK_NAMES = {
'leftx': [_('picture left')],
'less2': ['<'],
'list': ['list'],
- 'luminance': [_('brightness')],
'mediawait': [_('media wait')],
'minus2': ['–'],
'myfunc': [_('Python'), 'f(x)', 'x'],
@@ -630,7 +628,6 @@ DEFAULTS = {
'audio': [None],
'back': [100],
'box': [_('my box')],
- 'camera': ['CAMERA'],
'comment': [_('comment')],
'description': [None],
'fillscreen': [60, 80],
@@ -765,7 +762,6 @@ TEMPLATES = {'t1x1': (0.5, 0.5, 0.0625, 0.125, 1.05, 0),
#
SPECIAL_NAMES = {
'audio': _('audio'),
- 'camera': _('camera'),
'division2': _('divide'),
'equal2': _('equal'),
'greater2': _('greater than'),
@@ -805,7 +801,6 @@ HELP_STRINGS = {
'box1': _("Variable 1 (numeric value)"),
'box2': _("Variable 2 (numeric value)"),
'box': _("named variable (numeric value)"),
- 'camera': _('camera output'),
'cartesian': _("displays Cartesian coordinates"),
'clean': _("clears the screen and reset the turtle"),
'clearheap': _("emptys FILO (first-in-last-out heap)"),
@@ -843,7 +838,6 @@ HELP_STRINGS = {
'leftpos': _("xcor of left of screen"),
'left': _("turns turtle counterclockwise (angle in degrees)"),
'less2': _("logical less-than operator"),
- 'luminance': _("light level detected by camera"),
'media': _("Palette of media objects"),
'mediawait': _("wait for current video or audio to complete"),
'minus2': _("subtracts bottom numeric input from top numeric input"),
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index 421953f..38f2586 100644
--- a/TurtleArt/talogo.py
+++ b/TurtleArt/talogo.py
@@ -29,8 +29,6 @@ from numpy import append
from numpy.fft import rfft
from random import uniform
from operator import isNumberType
-from fcntl import ioctl
-import v4l2
import os.path
from UserDict import UserDict
@@ -55,7 +53,9 @@ from gettext import gettext as _
VALUE_BLOCKS = ['box1', 'box2', 'color', 'shade', 'gray', 'scale', 'pensize',
'heading', 'xcor', 'ycor', 'pop', 'time', 'keyboard', 'sound',
- 'volume', 'pitch', 'resistance', 'voltage', 'luminance', 'see']
+ 'volume', 'pitch', 'resistance', 'voltage', 'see']
+MEDIA_BLOCKS_DICTIONARY = {} # new media blocks get added here
+PLUGIN_DICTIONARY = {} # new block primitives get added here
import logging
_logger = logging.getLogger('turtleart-activity')
@@ -317,6 +317,7 @@ class LogoCode:
self.tw = tw
self.oblist = {}
+ # TODO: remove plugin blocks
DEFPRIM = {
'(': [1, lambda self, x: self._prim_opar(x)],
'and': [2, lambda self, x, y: _and(x, y)],
@@ -366,7 +367,6 @@ class LogoCode:
'leftx': [0, lambda self: CONSTANTS['leftx']],
'lpos': [0, lambda self: CONSTANTS['leftpos']],
'less?': [2, lambda self, x, y: _less(x, y)],
- 'luminance': [0, lambda self: self._read_camera(True)],
'mediawait': [0, self._media_wait, True],
'minus': [2, lambda self, x, y: _minus(x, y)],
'mod': [2, lambda self, x, y: _mod(x, y)],
@@ -394,7 +394,6 @@ class LogoCode:
'purple': [0, lambda self: CONSTANTS['purple']],
'push': [1, lambda self, x: self._prim_push(x)],
'random': [2, lambda self, x, y: _random(x, y)],
- 'readcamera': [0, lambda self: self._read_camera()],
'readpixel': [0, lambda self: self._read_pixel()],
'red': [0, lambda self: CONSTANTS['red']],
'repeat': [2, self._prim_repeat, True],
@@ -524,25 +523,16 @@ class LogoCode:
self.voltage_gain = -0.0001471
self.voltage_bias = 1.695
- if self.tw.camera_available:
- if self.tw.running_sugar:
- self.imagepath = get_path(self.tw.activity,
- 'data/turtlepic.png')
- else:
- self.imagepath = '/tmp/turtlepic.png'
- from tacamera import Camera
- self.camera = Camera(self.imagepath)
-
def stop_logo(self):
""" Stop logo is called from the Stop button on the toolbar """
self.tw.step_time = 0
self.step = _just_stop()
+ for p in self.tw._plugins:
+ print p.stop()
if self.tw.gst_available:
from tagplay import stop_media
stop_media(self)
- if self.tw.camera_available:
- self.camera.stop_camera_input()
- self.tw.active_turtle.show()
+ self.tw.active_turtle.show()
def _def_prim(self, name, args, fcn, rprim=False):
""" Define the primitives associated with the blocks """
@@ -633,8 +623,8 @@ class LogoCode:
str(blk.values[0]))
else:
code.append(PREFIX_DICTIONARY[blk.name] + 'None')
- elif blk.name == 'camera':
- code.append('#smedia_CAMERA')
+ elif blk.name in MEDIA_BLOCKS_DICTIONARY:
+ code.append('#smedia_' + blk.name.upper())
else:
return ['%nothing%']
else:
@@ -1091,7 +1081,8 @@ class LogoCode:
if flag and (self.tw.hide or self.tw.step_time == 0):
return
if type(n) == str or type(n) == unicode:
- if n[0:6] == 'media_' and n[6:] != 'CAMERA':
+ if n[0:6] == 'media_' and \
+ n[6:].lower not in MEDIA_BLOCKS_DICTIONARY:
try:
if self.tw.running_sugar:
try:
@@ -1325,11 +1316,9 @@ class LogoCode:
elif string[0:6] in ['media_', 'descr_', 'audio_', 'video_']:
self.filepath = None
self.dsobject = None
- if string[6:] == 'CAMERA':
- if self.tw.camera_available:
- self.camera.save_camera_input_to_file()
- self.camera.stop_camera_input()
- self.filepath = self.imagepath
+ print string[6:], MEDIA_BLOCKS_DICTIONARY
+ if string[6:].lower() in MEDIA_BLOCKS_DICTIONARY:
+ MEDIA_BLOCKS_DICTIONARY[string[6:].lower()]()
elif os.path.exists(string[6:]): # is it a path?
self.filepath = string[6:]
elif self.tw.running_sugar: # is it a datastore object?
@@ -1490,66 +1479,6 @@ class LogoCode:
self.heap.append(g)
self.heap.append(r)
- def _read_camera(self, luminance_only=False):
- """ Read average pixel from camera and push b, g, r to the stack """
- pixbuf = None
- array = None
- w, h = self._w(), self._h()
- if w > 0 and h > 0 and self.tw.camera_available:
- try:
- self._video_capture_device = open('/dev/video0', 'rw')
- except:
- self._video_capture_device = None
- _logger.debug('video capture device not available')
-
- if self._video_capture_device is not None:
- self._ag_control = v4l2.v4l2_control(v4l2.V4L2_CID_AUTOGAIN)
- try:
- ioctl(self._video_capture_device, v4l2.VIDIOC_G_CTRL,
- self._ag_control)
- self._ag_control.value = 0 # disable AUTOGAIN
- ioctl(self._video_capture_device, v4l2.VIDIOC_S_CTRL,
- self._ag_control)
- except:
- _logger.debug('AUTOGAIN control not available')
-
- if self._video_capture_device is not None:
- self._video_capture_device.close()
-
- self.camera.save_camera_input_to_file()
- self.camera.stop_camera_input()
- pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.imagepath, w, h)
- try:
- array = pixbuf.get_pixels()
- except:
- array = None
-
- if array is not None:
- length = len(array) / 3
- r, g, b, i = 0, 0, 0, 0
- for j in range(length):
- r += ord(array[i])
- i += 1
- g += ord(array[i])
- i += 1
- b += ord(array[i])
- i += 1
- if luminance_only:
- lum = int((r * 0.3 + g * 0.6 + b * 0.1) / length)
- self.update_label_value('luminance', lum)
- return lum
- else:
- self.heap.append(int((b / length)))
- self.heap.append(int((g / length)))
- self.heap.append(int((r / length)))
- else:
- if luminance_only:
- return -1
- else:
- self.heap.append(-1)
- self.heap.append(-1)
- self.heap.append(-1)
-
def _get_volume(self):
""" return mic in value """
#TODO: Adjust gain for different HW
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index b67f604..73894e4 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -105,6 +105,9 @@ _logger = logging.getLogger('turtleart-activity')
class TurtleArtWindow():
""" TurtleArt Window class abstraction """
timeout_tag = [0]
+ _INSTALL_PATH = '/usr/share/turtleart'
+ _ALTERNATE_INSTALL_PATH = '/usr/local/share/turtleart'
+ _PLUGIN_SUBPATH = 'plugins'
def __init__(self, win, path, parent=None, mycolors=None, mynick=None):
self._loaded_project = ''
@@ -276,18 +279,13 @@ class TurtleArtWindow():
PALETTES[PALETTE_NAMES.index('sensor')].append('voltage')
self.audio_started = False
- self.camera_available = False
- if self.gst_available:
- v4l2src = gst.element_factory_make('v4l2src')
- if v4l2src.props.device_name is not None:
- PALETTES[PALETTE_NAMES.index('sensor')].append('readcamera')
- PALETTES[PALETTE_NAMES.index('sensor')].append('luminance')
- PALETTES[PALETTE_NAMES.index('sensor')].append('camera')
- self.camera_available = True
+ self._plugins = []
+ self._init_plugins()
self.lc = LogoCode(self)
- self.saved_pictures = []
+ self._run_plugins()
+ self.saved_pictures = []
self.block_operation = ''
"""
@@ -324,6 +322,60 @@ class TurtleArtWindow():
PALETTES[PALETTE_NAMES.index('sensor')].append('rfid')
+ ####
+
+ def _get_plugin_home(self):
+ """ Look in current directory first, then usual places """
+ path = os.path.join(os.getcwd(), self._PLUGIN_SUBPATH)
+ if os.path.exists(path):
+ return path
+ path = os.path.expanduser(os.path.join('~', 'Activities',
+ 'TurtleBlocks.activity',
+ self._PLUGIN_SUBPATH))
+ if os.path.exists(path):
+ return path
+ path = os.path.expanduser(os.path.join('~', 'Activities',
+ 'TurtleArt.activity',
+ self._PLUGIN_SUBPATH))
+ if os.path.exists(path):
+ return path
+ path = os.path.join(self._INSTALL_PATH, self._PLUGIN_SUBPATH)
+ if os.path.exists(path):
+ return path
+ path = os.path.join(self._ALTERNATE_INSTALL_PATH,
+ self._PLUGIN_SUBPATH)
+ if os.path.exists(path):
+ return path
+ return None
+
+ def _get_plugin_candidates(self, path):
+ """ Look for plugin files in plugin directory. """
+ plugin_files = []
+ if path is not None:
+ candidates = os.listdir(path)
+ for c in candidates:
+ if c[-10:] == '_plugin.py' and c[0] != '#' and c[0] != '.':
+ plugin_files.append(c.split('.')[0])
+ return plugin_files
+
+ def _init_plugins(self):
+ for p in self._get_plugin_candidates(self._get_plugin_home()):
+ P = p.capitalize()
+ f = "def f(self): from plugins.%s import %s; return %s(self)" \
+ % (p, P, P)
+ plugin = {}
+ try:
+ exec f in globals(), plugin
+ self._plugins.append(plugin.values()[0](self))
+ except ImportError:
+ print 'failed to import %s' % (P)
+
+ def _run_plugins(self):
+ for p in self._plugins:
+ p.setup()
+
+ ####
+
def _device_added_cb(self, path):
"""
Called from hal connection when a new device is plugged.
@@ -1602,6 +1654,7 @@ class TurtleArtWindow():
blk.spr.labels[0] += CURSOR
elif blk.name in BOX_STYLE_MEDIA and blk.name != 'camera':
+ # TODO: isolate reference to camera
self._import_from_journal(self.selected_blk)
if blk.name == 'journal' and self.running_sugar:
self._load_description_block(blk)
@@ -2533,6 +2586,7 @@ class TurtleArtWindow():
else:
self._block_skin('pythonoff', blk)
elif btype in BOX_STYLE_MEDIA and blk.spr is not None:
+ # TODO: isolate reference to camera
if len(blk.values) == 0 or blk.values[0] == 'None' or \
blk.values[0] is None or btype == 'camera':
self._block_skin(btype + 'off', blk)