From 1d6e73c2e7a9ab9bba0b028c5c567d2106d7f1cf Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 10 Oct 2012 19:37:51 +0000 Subject: add support for USB camera (e.g., microscope) --- (limited to 'plugins/camera_sensor') 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 @@ + + + +image/svg+xml + + + + + + + + + + +2 + \ 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 @@ + + + +image/svg+xml + + + + + + + + + + 2 + \ 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 ''' -- cgit v0.9.1