Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2010-12-24 17:10:15 (GMT)
committer Walter Bender <walter@sugarlabs.org>2010-12-24 17:10:15 (GMT)
commit78238ca84096c928d26ba887408a91fbeaa5dce8 (patch)
treef0609cbea0638d7442a8ff86a02da7a15bb82eac
parente46e62a5d45add8fb1e951916adb51f0ff9b9df2 (diff)
adding camera blocks
-rw-r--r--TurtleArt/tacamera.py35
-rwxr-xr-x[-rw-r--r--]TurtleArt/taconstants.py18
-rwxr-xr-xTurtleArt/talogo.py46
-rwxr-xr-x[-rw-r--r--]TurtleArt/tawindow.py4
4 files changed, 93 insertions, 10 deletions
diff --git a/TurtleArt/tacamera.py b/TurtleArt/tacamera.py
new file mode 100644
index 0000000..f7e08ff
--- /dev/null
+++ b/TurtleArt/tacamera.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+#Copyright (c) 2010, Walter Bender
+#Copyright (c) 2010, Tony Forster
+
+#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 gst, time
+
+def save_camera_input_to_file(imagepath):
+ """ Grab a frame from the video camera and save to a temporary file """
+
+ pipeline = gst.parse_launch(
+ 'v4l2src ! ffmpegcolorspace ! jpegenc ! filesink location=' + imagepath)
+ pipeline.set_state(gst.STATE_PLAYING)
+
+ # Need to pause for pipeline to stablize
+ time.sleep(2)
+
+ pipeline.set_state(gst.STATE_NULL)
diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py
index 0ec31aa..4f45663 100644..100755
--- a/TurtleArt/taconstants.py
+++ b/TurtleArt/taconstants.py
@@ -136,8 +136,8 @@ PALETTES = [['clean', 'forward', 'back', 'show', 'left', 'right',
'myfunc1arg', 'userdefined',
'cartesian', 'width', 'height', 'polar', 'addturtle', 'reskin',
'sandwichtop_no_label', 'sandwichbottom'],
- ['kbinput', 'keyboard', 'readpixel', 'see', 'sound', 'volume',
- 'pitch'],
+ ['kbinput', 'keyboard', 'readpixel', 'see', 'readcamera', 'camera',
+ 'sound', 'volume', 'pitch'],
['journal', 'audio', 'video', 'description', 'hideblocks',
'showblocks', 'fullscreen', 'savepix', 'savesvg', 'mediawait',
'picturelist', 'picture1x1a', 'picture1x1', 'picture2x2',
@@ -205,7 +205,7 @@ BASIC_STYLE = []
BASIC_STYLE_EXTENDED_VERTICAL = ['clean', 'penup', 'pendown', 'stack1',
'stack2', 'hideblocks', 'showblocks', 'clearheap', 'printheap', 'kbinput',
'fullscreen', 'cartesian', 'polar', 'startfill', 'mediawait',
- 'stopfill', 'readpixel', 'vspace']
+ 'stopfill', 'readpixel', 'readcamera', 'vspace']
INVISIBLE = ['sandwichcollapsed']
BASIC_STYLE_EXTENDED = ['picturelist', 'picture1x1', 'picture2x2',
'picture2x1', 'picture1x2', 'picture1x1a']
@@ -223,7 +223,7 @@ 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']
-BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video']
+BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video', 'camera']
NUMBER_STYLE = ['plus2', 'product2', 'myfunc']
NUMBER_STYLE_VAR_ARG = ['myfunc1arg', 'myfunc2arg', 'myfunc3arg']
NUMBER_STYLE_BLOCK = ['random']
@@ -277,7 +277,7 @@ OLD_DOCK = ['and', 'or', 'plus', 'minus', 'division', 'product', 'remainder']
# Blocks that contain media
#
CONTENT_BLOCKS = ['number', 'string', 'description', 'audio', 'video',
- 'journal']
+ 'journal', 'camera']
#
# These blocks get a special skin
@@ -313,6 +313,7 @@ BLOCK_NAMES = {
'box': [_('box')],
'box1': [_('box 1')],
'box2': [_('box 2')],
+ 'camera': [' '],
'cartesian': [_('Cartesian')],
'clean': [_(' clean ')],
'clearheap': [_('empty heap')],
@@ -385,6 +386,7 @@ BLOCK_NAMES = {
'purple': [_('purple')],
'push': [_('push')],
'random': [_('random'), _('min'), _('max')],
+ 'readcamera': [_('read camera')],
'readpixel': [_('read pixel')],
'red': [_('red')],
'remainder2': [_('mod')],
@@ -540,6 +542,7 @@ PRIMITIVES = {
'push': 'push',
'random': 'random',
'red': 'red',
+ 'readcamera': 'readcamera',
'readpixel': 'readpixel',
'remainder2': 'mod',
'repeat': 'repeat',
@@ -621,6 +624,7 @@ DEFAULTS = {
'audio': [None],
'back': [100],
'box': [_('my box')],
+ 'camera': ['CAMERA'],
'comment': [_('comment')],
'description': [None],
'fillscreen': [60, 80],
@@ -696,6 +700,7 @@ CONTENT_ARGS = ['show', 'showaligned', 'push', 'storein', 'storeinbox1',
MEDIA_SHAPES = ['audiooff', 'audioon', 'audiosmall',
'videooff', 'videoon', 'videosmall',
+ 'cameraoff', 'camerasmall',
'journaloff', 'journalon', 'journalsmall',
'descriptionoff', 'descriptionon', 'descriptionsmall',
'pythonoff', 'pythonon', 'pythonsmall',
@@ -751,6 +756,7 @@ 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'),
@@ -790,6 +796,7 @@ 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)"),
@@ -860,6 +867,7 @@ HELP_STRINGS = {
'product2': _("multiplies two numeric inputs"),
'push': _("pushes value onto FILO (first-in last-out heap)"),
'random': _("returns random number between minimum (top) and maximum (bottom) values"),
+ 'readcamera': _("Average RGB color from camera is pushed to the stack"),
'readpixel': _("RGB color under the turtle is pushed to the stack"),
'remainder2': _("modular (remainder) operator"),
'repeat': _("loops specified number of times"),
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index bab3b0a..2da8685 100755
--- a/TurtleArt/talogo.py
+++ b/TurtleArt/talogo.py
@@ -44,9 +44,10 @@ from taconstants import TAB_LAYER, BLACK, WHITE, \
SENSOR_DC_BIAS, XO1, XO15
from tagplay import play_audio_from_file, play_movie_from_file, stop_media, \
media_playing
+from tacamera import save_camera_input_to_file
from tajail import myfunc, myfunc_import
from tautils import get_pixbuf_from_journal, convert, data_from_file, \
- text_media_type, round_int, chr_to_ord, strtype
+ text_media_type, round_int, chr_to_ord, strtype, get_path
from RtfParser import RtfTextOnly
@@ -401,6 +402,7 @@ 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],
@@ -527,6 +529,12 @@ class LogoCode:
self.voltage_gain = -0.0001471
self.voltage_bias = 1.695
+ if self.tw.running_sugar:
+ self.imagepath = get_path(self.tw.activity,
+ 'data/turtlepic.jpg')
+ else:
+ self.imagepath = '/tmp/turtlepic.jpg'
+
def _def_prim(self, name, args, fcn, rprim=False):
""" Define the primitives associated with the blocks """
sym = self._intern(name)
@@ -628,6 +636,8 @@ class LogoCode:
code.append('#svideo_' + str(blk.values[0]))
else:
code.append('#svideo_None')
+ elif blk.name == 'camera':
+ code.append('#smedia_CAMERA')
else:
return ['%nothing%']
else:
@@ -1303,7 +1313,6 @@ class LogoCode:
def _show(self, string, center=False):
""" Show is the general-purpose media-rendering block. """
- # convert from Turtle coordinates to screen coordinates
if type(string) == str or type(string) == unicode:
if string in ['media_', 'descr_', 'audio_', 'video_',
'media_None', 'descr_None', 'audio_None',
@@ -1312,7 +1321,10 @@ class LogoCode:
elif string[0:6] in ['media_', 'descr_', 'audio_', 'video_']:
self.filepath = None
dsobject = None
- if os.path.exists(string[6:]): # is it a path?
+ if string[6:] == 'CAMERA':
+ save_camera_input_to_file(self.imagepath)
+ self.filepath = self.imagepath
+ elif os.path.exists(string[6:]): # is it a path?
self.filepath = string[6:]
elif self.tw.running_sugar: # is it a datastore object?
try:
@@ -1449,6 +1461,34 @@ class LogoCode:
self.heap.append(g)
self.heap.append(r)
+ def _read_camera(self):
+ """ Read average pixel from camera and push b, g, r to the stack """
+ save_camera_input_to_file(self.imagepath)
+ pixbuf = None
+ w = self._w()
+ h = self._h()
+ if w < 1 or h < 1:
+ return
+ pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.imagepath, w, h)
+
+ array = pixbuf.get_pixels()
+ length = len(array) / 3
+ r = 0
+ g = 0
+ b = 0
+ i = 0
+ if array is not None:
+ for j in range(length):
+ r += ord(array[i])
+ i += 1
+ g += ord(array[i])
+ i += 1
+ b += ord(array[i])
+ i += 1
+ self.heap.append(int((b / length)))
+ self.heap.append(int((g / length)))
+ self.heap.append(int((r / length)))
+
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 b67dee5..ceb9a69 100644..100755
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -1572,7 +1572,7 @@ class TurtleArtWindow():
self.saved_string = blk.spr.labels[0]
blk.spr.labels[0] += CURSOR
- elif blk.name in BOX_STYLE_MEDIA:
+ elif blk.name in BOX_STYLE_MEDIA and blk.name != 'camera':
self._import_from_journal(self.selected_blk)
if blk.name == 'journal' and self.running_sugar:
self._load_description_block(blk)
@@ -2504,7 +2504,7 @@ class TurtleArtWindow():
self._block_skin('pythonoff', blk)
elif btype in BOX_STYLE_MEDIA and blk.spr is not None:
if len(blk.values) == 0 or blk.values[0] == 'None' or \
- blk.values[0] is None:
+ blk.values[0] is None or btype == 'camera':
self._block_skin(btype + 'off', blk)
elif btype == 'video' or btype == 'audio' or \
btype == 'description':