diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/camera_sensor/camera_sensor.py | 97 | ||||
-rw-r--r-- | plugins/camera_sensor/images/camera1off.svg | 63 | ||||
-rw-r--r-- | plugins/camera_sensor/images/camera1small.svg | 61 | ||||
-rw-r--r-- | plugins/camera_sensor/tacamera.py | 26 |
4 files changed, 211 insertions, 36 deletions
diff --git a/plugins/camera_sensor/camera_sensor.py b/plugins/camera_sensor/camera_sensor.py index ebbd5e8..6509a88 100644 --- a/plugins/camera_sensor/camera_sensor.py +++ b/plugins/camera_sensor/camera_sensor.py @@ -43,11 +43,17 @@ class Camera_sensor(Plugin): self._parent = parent self._status = False self._ag_control = None - self.camera = None - - v4l2src = gst.element_factory_make('v4l2src') - if v4l2src.props.device_name is not None: + self.devices = [] + self.cameras = [] + + if os.path.exists('/dev/video0'): + self.devices.append('/dev/video0') + if os.path.exists('/dev/video1'): + self.devices.append('/dev/video1') + if len(self.devices) > 0: self._status = True + else: + self._status = False def setup(self): ''' Set up the palettes ''' @@ -63,7 +69,8 @@ class Camera_sensor(Plugin): # set up camera-specific blocks primitive_dictionary['read_camera'] = self.prim_read_camera - media_blocks_dictionary['camera'] = self.prim_take_picture + media_blocks_dictionary['camera'] = self.prim_take_picture0 + media_blocks_dictionary['camera1'] = self.prim_take_picture1 SKIN_PATHS.append('plugins/camera_sensor/images') @@ -98,6 +105,22 @@ is pushed to the stack'), default='CAMERA', help_string=_('camera output'), content_block=True) + if len(self.devices) > 1: + media_palette.add_block('camera1', + style='box-style-media', + label=' ', + default='CAMERA', + help_string=_('camera output'), + content_block=True) + else: + media_palette.add_block('camera1', + hidden=True, + style='box-style-media', + label=' ', + default='CAMERA', + help_string=_('camera output'), + content_block=True) + else: # No camera, so blocks should do nothing sensors_palette.add_block('luminance', hidden=True, @@ -132,17 +155,30 @@ is pushed to the stack'), help_string=_('camera output'), content_block=True) + media_palette.add_block('camera1', + hidden=True, + style='box-style-media', + label=' ', + default='CAMERA', + help_string=_('camera output'), + content_block=True) + NO_IMPORT.append('camera') BLOCKS_WITH_SKIN.append('camera') + NO_IMPORT.append('camera1') + BLOCKS_WITH_SKIN.append('camera1') MEDIA_SHAPES.append('camerasmall') MEDIA_SHAPES.append('cameraoff') + MEDIA_SHAPES.append('camera1small') + MEDIA_SHAPES.append('camera1off') def start(self): ''' Initialize the camera if there is an camera block in use ''' if len(self._parent.block_list.get_similar_blocks('block', - ['camera', 'read_camera', 'luminance'])) > 0: - if self._status and self.camera is None: - self.camera = Camera() + ['camera', 'camera1', 'read_camera', 'luminance'])) > 0: + if self._status and len(self.cameras) == 0: + for device in self.devices: + self.cameras.append(Camera(device)) def quit(self): ''' This gets called when the activity quits ''' @@ -157,9 +193,10 @@ is pushed to the stack'), self._reset_the_camera() def _reset_the_camera(self): - if self._status and self.camera is not None: - self.camera.stop_camera_input() - self._set_autogain(1) # enable AUTOGAIN + if self._status and len(self.cameras) > 0: + for i, camera in enumerate(self.cameras): + camera.stop_camera_input() + self._set_autogain(1, camera=i) # enable AUTOGAIN def _status_report(self): debug_output('Reporting camera status: %s' % (str(self._status)), @@ -168,13 +205,19 @@ is pushed to the stack'), # Block primitives used in talogo - def prim_take_picture(self): + def prim_take_picture0(self): + self._take_picture(camera=0) + + def prim_take_picture1(self): + self._take_picture(camera=1) + + def _take_picture(self, camera=0): ''' method called by media block ''' - self._set_autogain(1) # enable AUTOGAIN - self._get_pixbuf_from_camera() - self._parent.lc.pixbuf = self.camera.pixbuf + self._set_autogain(1, camera) # enable AUTOGAIN + self._get_pixbuf_from_camera(camera) + self._parent.lc.pixbuf = self.cameras[camera].pixbuf - def prim_read_camera(self, luminance_only=False): + def prim_read_camera(self, luminance_only=False, camera=0): """ Read average pixel from camera and push b, g, r to the stack """ self.luminance_only = luminance_only if not self._status: @@ -187,9 +230,9 @@ is pushed to the stack'), return array = None - self._set_autogain(0) # disable AUTOGAIN - self._get_pixbuf_from_camera() - self.calc_luminance() + self._set_autogain(0, camera=camera) # disable AUTOGAIN + self._get_pixbuf_from_camera(camera=camera) + self.calc_luminance(camera=camera) if self.luminance_only: self._parent.lc.update_label_value('luminance', self.luminance) return self.luminance @@ -198,10 +241,10 @@ is pushed to the stack'), self._parent.lc.heap.append(self.g) self._parent.lc.heap.append(self.r) - def calc_luminance(self): - array = self.camera.pixbuf.get_pixels() - width = self.camera.pixbuf.get_width() - height = self.camera.pixbuf.get_height() + def calc_luminance(self, camera=0): + array = self.cameras[camera].pixbuf.get_pixels() + width = self.cameras[camera].pixbuf.get_width() + height = self.cameras[camera].pixbuf.get_height() if array is not None: length = int(len(array) / 3) @@ -238,12 +281,12 @@ is pushed to the stack'), self.g = -1 self.b = -1 - def _set_autogain(self, state): + def _set_autogain(self, state, camera=0): ''' 0 is off; 1 is on ''' if self._ag_control is not None and self._ag_control.value == state: return try: - video_capture_device = open('/dev/video0', 'rw') + video_capture_device = open(self.devices[camera], 'rw') except: video_capture_device = None debug_output('video capture device not available', @@ -258,8 +301,8 @@ is pushed to the stack'), pass video_capture_device.close() - def _get_pixbuf_from_camera(self): + def _get_pixbuf_from_camera(self, camera): ''' Regardless of how we get it, we want to return a pixbuf ''' self._parent.lc.pixbuf = None if self._status: - self.camera.start_camera_input() + self.cameras[camera].start_camera_input() diff --git a/plugins/camera_sensor/images/camera1off.svg b/plugins/camera_sensor/images/camera1off.svg new file mode 100644 index 0000000..aa25260 --- /dev/null +++ b/plugins/camera_sensor/images/camera1off.svg @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata23"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs21" /><g + id="camera-external" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:block"> + <g + id="g5" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"> + <g + id="g7" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <polygon + points="34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 38.532,14.52 " + id="polygon9" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + id="g11" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <polygon + points="34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 38.532,14.52 " + id="polygon13" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> + <path + d="m 20.601,26.441 c 0,3.67 2.979,6.648 6.65,6.648 3.667,0 6.646,-2.979 6.646,-6.648 0,-3.668 -2.979,-6.652 -6.646,-6.652 -3.67,0 -6.65,2.986 -6.65,6.652 z" + id="path15" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" /> + <rect + width="6.2870002" + height="4.1929998" + x="38.098999" + y="18.417999" + id="rect17" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" /> +</g><text + x="45.716103" + y="51.309322" + id="text3000" + xml:space="preserve" + style="font-size:11px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="45.716103" + y="51.309322" + id="tspan3002" + style="font-weight:bold;-inkscape-font-specification:Sans Bold">2</tspan></text> +</svg>
\ No newline at end of file diff --git a/plugins/camera_sensor/images/camera1small.svg b/plugins/camera_sensor/images/camera1small.svg new file mode 100644 index 0000000..8b081f3 --- /dev/null +++ b/plugins/camera_sensor/images/camera1small.svg @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="26" + height="18.668091" + viewBox="0 0 26 18.668091" + id="svg2" + xml:space="preserve"><metadata + id="metadata29"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs27"> + + + + + + + + + + </defs><g + transform="matrix(0.57244766,0,0,0.57244766,-2.5989125,-4.6436954)" + id="camera-external" + style="display:block"><g + id="g5" + style="display:inline"><g + id="g7"><polygon + points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 " + id="polygon9" + style="fill:#ffffff" /></g><g + id="g11"><polygon + points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 " + id="polygon13" + style="fill:none;stroke:#010101;stroke-width:3.5" /></g></g><path + d="m 20.601,26.441 c 0,3.67 2.979,6.648 6.65,6.648 3.667,0 6.646,-2.979 6.646,-6.648 0,-3.668 -2.979,-6.652 -6.646,-6.652 -3.67,0 -6.65,2.986 -6.65,6.652 z" + id="path15" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5;display:inline" /><rect + width="6.2870002" + height="4.1929998" + x="38.098999" + y="18.417999" + id="rect17" + style="fill:#010101;display:inline" /></g><text + x="18.149788" + y="15.630935" + id="text3000" + xml:space="preserve" + style="font-size:11px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="18.149788" + y="15.630935" + id="tspan3002" + style="font-size:8px;font-weight:bold;-inkscape-font-specification:Sans Bold">2</tspan></text> +</svg>
\ No newline at end of file diff --git a/plugins/camera_sensor/tacamera.py b/plugins/camera_sensor/tacamera.py index 5a6f506..fc0804d 100644 --- a/plugins/camera_sensor/tacamera.py +++ b/plugins/camera_sensor/tacamera.py @@ -25,24 +25,33 @@ import gobject from TurtleArt.tautils import debug_output -GST_PIPE = ['v4l2src', 'ffmpegcolorspace', 'gdkpixbufsink'] - class Camera(): ''' Sets up a pipe from the camera to a pixbuf and emits a signal when the image is ready. ''' - def __init__(self): + def __init__(self, device='/dev/video0'): ''' Prepare camera pipeline to pixbuf and signal watch ''' - self.pipe = gst.parse_launch('!'.join(GST_PIPE)) - self.bus = self.pipe.get_bus() - self.bus.add_signal_watch() - self.bus.connect('message', self._on_message) + self.pipe = gst.Pipeline('pipeline') + v4l2src = gst.element_factory_make('v4l2src', None) + v4l2src.props.device = device + self.pipe.add(v4l2src) + ffmpegcolorspace = gst.element_factory_make('ffmpegcolorspace', None) + self.pipe.add(ffmpegcolorspace) + gdkpixbufsink = gst.element_factory_make('gdkpixbufsink', None) + self.pipe.add(gdkpixbufsink) + gst.element_link_many(v4l2src, ffmpegcolorspace, gdkpixbufsink) + if self.pipe is not None: + self.bus = self.pipe.get_bus() + self.bus.add_signal_watch() + self.bus.connect('message', self._on_message) + status = True + else: + status = False def _on_message(self, bus, message): ''' We get a message if a pixbuf is available ''' if message.structure is not None: - # debug_output(message.structure.get_name(), True) if message.structure.get_name() == 'pixbuf': self.pixbuf = message.structure['pixbuf'] self.image_ready = True @@ -54,7 +63,6 @@ class Camera(): self.pipe.set_state(gst.STATE_PLAYING) while not self.image_ready: self.bus.poll(gst.MESSAGE_ANY, -1) - # self.stop_camera_input() def stop_camera_input(self): ''' Stop grabbing ''' |