diff options
author | Lionel Landwerlin <llandwerlin@gmail.com> | 2013-08-08 16:38:59 +0100 |
---|---|---|
committer | Lionel Landwerlin <llandwerlin@gmail.com> | 2013-08-09 18:04:33 +0100 |
commit | 37d116d2c997f1a0c933f53f82eb2f3d8eb13808 (patch) | |
tree | 55648c898809c36e4983cea4547700b95ad1e3cf | |
parent | c8761d445985a045986db855363e9b6117df7f77 (diff) | |
download | clutter-gst-37d116d2c997f1a0c933f53f82eb2f3d8eb13808.tar.gz |
camera: move device list to its own component
-rw-r--r-- | clutter-gst/Makefile.am | 2 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-camera-manager.c | 259 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-camera-manager.h | 98 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-camera.c | 153 | ||||
-rw-r--r-- | clutter-gst/clutter-gst-camera.h | 2 | ||||
-rw-r--r-- | clutter-gst/clutter-gst.h | 1 | ||||
-rw-r--r-- | doc/reference/clutter-gst-sections.txt | 20 | ||||
-rw-r--r-- | examples/camera-player.c | 2 |
8 files changed, 398 insertions, 139 deletions
diff --git a/clutter-gst/Makefile.am b/clutter-gst/Makefile.am index fb88f27..1b6e594 100644 --- a/clutter-gst/Makefile.am +++ b/clutter-gst/Makefile.am @@ -26,6 +26,7 @@ source_h = \ $(srcdir)/clutter-gst-util.h \ $(srcdir)/clutter-gst-version.h \ $(srcdir)/clutter-gst-camera.h \ + $(srcdir)/clutter-gst-camera-manager.h \ $(srcdir)/clutter-gst-camera-device.h \ $(srcdir)/clutter-gst-playback.h \ $(srcdir)/clutter-gst-player.h \ @@ -46,6 +47,7 @@ source_c = \ $(srcdir)/clutter-gst-marshal.c \ $(srcdir)/clutter-gst-player.c \ $(srcdir)/clutter-gst-camera.c \ + $(srcdir)/clutter-gst-camera-manager.c \ $(srcdir)/clutter-gst-camera-device.c \ $(srcdir)/clutter-gst-playback.c \ $(srcdir)/clutter-gst-util.c \ diff --git a/clutter-gst/clutter-gst-camera-manager.c b/clutter-gst/clutter-gst-camera-manager.c new file mode 100644 index 0000000..b614c27 --- /dev/null +++ b/clutter-gst/clutter-gst-camera-manager.c @@ -0,0 +1,259 @@ +/* + * Clutter-GStreamer. + * + * GStreamer integration library for Clutter. + * + * clutter-gst-camera-manager.c - a component to list available cameras + * + * Authored By Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com> + * + * Copyright (C) 2013 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:clutter-gst-camera-manager + * @short_description: A component to list available cameras. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include <gst/gst.h> +#ifdef HAVE_GUDEV +#include <gudev/gudev.h> +#endif + +#include "clutter-gst-camera-manager.h" +#include "clutter-gst-camera-device.h" + +G_DEFINE_TYPE (ClutterGstCameraManager, clutter_gst_camera_manager, G_TYPE_OBJECT) + +#define GST_CAMERA_MANAGER_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), CLUTTER_GST_TYPE_CAMERA_MANAGER, ClutterGstCameraManagerPrivate)) + +struct _ClutterGstCameraManagerPrivate +{ + GPtrArray *camera_devices; +}; + + +static void +clutter_gst_camera_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +clutter_gst_camera_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +clutter_gst_camera_manager_dispose (GObject *object) +{ + ClutterGstCameraManagerPrivate *priv = CLUTTER_GST_CAMERA_MANAGER (object)->priv; + + if (priv->camera_devices) + { + g_ptr_array_unref (priv->camera_devices); + priv->camera_devices = NULL; + } + + + G_OBJECT_CLASS (clutter_gst_camera_manager_parent_class)->dispose (object); +} + +static void +clutter_gst_camera_manager_finalize (GObject *object) +{ + G_OBJECT_CLASS (clutter_gst_camera_manager_parent_class)->finalize (object); +} + +static void +clutter_gst_camera_manager_class_init (ClutterGstCameraManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (ClutterGstCameraManagerPrivate)); + + object_class->get_property = clutter_gst_camera_manager_get_property; + object_class->set_property = clutter_gst_camera_manager_set_property; + object_class->dispose = clutter_gst_camera_manager_dispose; + object_class->finalize = clutter_gst_camera_manager_finalize; +} + +static void +add_device (ClutterGstCameraManager *self, + GstElementFactory *element_factory, + const gchar *device_node, + const gchar *device_name) +{ + ClutterGstCameraManagerPrivate *priv = self->priv; + ClutterGstCameraDevice *device; + + if (!priv->camera_devices) + priv->camera_devices = + g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + + device = g_object_new (CLUTTER_GST_TYPE_CAMERA_DEVICE, + "element-factory", element_factory, + "node", device_node, + "name", device_name, + NULL); + g_ptr_array_add (priv->camera_devices, device); +} + +static gboolean +probe_camera_devices (ClutterGstCameraManager *self) +{ + ClutterGstCameraManagerPrivate *priv = self->priv; + GstElement *videosrc; + GstElementFactory *element_factory; + GParamSpec *pspec; + gchar *device_node; + gchar *device_name; +#ifdef HAVE_GUDEV + GUdevClient *udev_client; + GList *udevices, *l; + GUdevDevice *udevice; +#endif + + videosrc = gst_element_factory_make ("v4l2src", "v4l2src"); + if (!videosrc) + { + g_warning ("Unable to get available camera devices, " + "v4l2src element missing"); + return FALSE; + } + + pspec = g_object_class_find_property ( + G_OBJECT_GET_CLASS (G_OBJECT (videosrc)), "device"); + if (!G_IS_PARAM_SPEC_STRING (pspec)) + { + g_warning ("Unable to get available camera devices, " + "v4l2src has no 'device' property"); + goto out; + } + + element_factory = gst_element_get_factory (videosrc); + +#ifdef HAVE_GUDEV + udev_client = g_udev_client_new (NULL); + udevices = g_udev_client_query_by_subsystem (udev_client, "video4linux"); + for (l = udevices; l != NULL; l = l->next) + { + gint v4l_version; + + udevice = (GUdevDevice *) l->data; + v4l_version = g_udev_device_get_property_as_int (udevice, "ID_V4L_VERSION"); + if (v4l_version == 2) + { + const char *caps; + + caps = g_udev_device_get_property (udevice, "ID_V4L_CAPABILITIES"); + if (caps == NULL || strstr (caps, ":capture:") == NULL) + continue; + + device_node = (gchar *) g_udev_device_get_device_file (udevice); + device_name = (gchar *) g_udev_device_get_property (udevice, "ID_V4L_PRODUCT"); + + add_device (self, element_factory, device_node, device_name); + } + + g_object_unref (udevice); + } + g_list_free (udevices); + g_object_unref (udev_client); +#else + /* GStreamer 1.0 does not support property probe, adding default detected + * device as only known device */ + g_object_get (videosrc, "device", &device_node, NULL); + g_object_get (videosrc, "device-name", &device_name, NULL); + add_device (self, element_factory, device_node, device_name); + + g_free (device_node); + g_free (device_name); +#endif + + out: + gst_object_unref (videosrc); + return (priv->camera_devices != NULL); +} + +static void +clutter_gst_camera_manager_init (ClutterGstCameraManager *self) +{ + self->priv = GST_CAMERA_MANAGER_PRIVATE (self); +} + +/** + * clutter_gst_camera_manager_get_default: + * + * Get the camera manager. + * + * <note>This function has to be called from Clutter's main + * thread.</note> + * + * Return value: (transfer none): the default camera manager. + */ +ClutterGstCameraManager * +clutter_gst_camera_manager_get_default (void) +{ + static ClutterGstCameraManager *manager = NULL; + + if (G_UNLIKELY (manager == NULL)) + manager = g_object_new (CLUTTER_GST_TYPE_CAMERA_MANAGER, NULL); + + return manager; +} + +/** + * clutter_gst_camera_manager_get_camera_devices: + * @self: a #ClutterGstCameraManager + * + * Retrieve an array of supported camera devices. + * + * Return value: (transfer none) (element-type ClutterGst.CameraDevice): An array of #ClutterGstCameraDevice representing + * the supported camera devices + */ +const GPtrArray * +clutter_gst_camera_manager_get_camera_devices (ClutterGstCameraManager *self) +{ + g_return_val_if_fail (CLUTTER_GST_IS_CAMERA_MANAGER (self), NULL); + + return self->priv->camera_devices; +} diff --git a/clutter-gst/clutter-gst-camera-manager.h b/clutter-gst/clutter-gst-camera-manager.h new file mode 100644 index 0000000..c17f884 --- /dev/null +++ b/clutter-gst/clutter-gst-camera-manager.h @@ -0,0 +1,98 @@ +/* + * Clutter-GStreamer. + * + * GStreamer integration library for Clutter. + * + * clutter-gst-camera-manager.h - a component to list available cameras + * + * Authored By Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com> + * + * Copyright (C) 2013 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_GST_CAMERA_MANAGER_H__ +#define __CLUTTER_GST_CAMERA_MANAGER_H__ + +#if !defined(__CLUTTER_GST_H_INSIDE__) && !defined(CLUTTER_GST_COMPILATION) +#error "Only <clutter-gst/clutter-gst.h> can be included directly." +#endif + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define CLUTTER_GST_TYPE_CAMERA_MANAGER clutter_gst_camera_manager_get_type() + +#define CLUTTER_GST_CAMERA_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_GST_TYPE_CAMERA_MANAGER, ClutterGstCameraManager)) + +#define CLUTTER_GST_CAMERA_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_GST_TYPE_CAMERA_MANAGER, ClutterGstCameraManagerClass)) + +#define CLUTTER_GST_IS_CAMERA_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_GST_TYPE_CAMERA_MANAGER)) + +#define CLUTTER_GST_IS_CAMERA_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_GST_TYPE_CAMERA_MANAGER)) + +#define CLUTTER_GST_CAMERA_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_GST_TYPE_CAMERA_MANAGER, ClutterGstCameraManagerClass)) + +typedef struct _ClutterGstCameraManager ClutterGstCameraManager; +typedef struct _ClutterGstCameraManagerClass ClutterGstCameraManagerClass; +typedef struct _ClutterGstCameraManagerPrivate ClutterGstCameraManagerPrivate; + +/** + * ClutterGstCameraManager: + * + * An object to list available cameras on the system. + * + * The #ClutterGstCameraManager structure contains only private data and + * should not be accessed directly. + */ +struct _ClutterGstCameraManager +{ + GObject parent; + + ClutterGstCameraManagerPrivate *priv; +}; + +/** + * ClutterGstCameraManagerClass: + * + * Base class for #ClutterGstCamera. + */ +struct _ClutterGstCameraManagerClass +{ + GObjectClass parent_class; +}; + +GType clutter_gst_camera_manager_get_type (void) G_GNUC_CONST; + +ClutterGstCameraManager *clutter_gst_camera_manager_get_default (void); + +const GPtrArray *clutter_gst_camera_manager_get_camera_devices (ClutterGstCameraManager *self); + +G_END_DECLS + +#endif /* __CLUTTER_GST_CAMERA_MANAGER_H__ */ diff --git a/clutter-gst/clutter-gst-camera.c b/clutter-gst/clutter-gst-camera.c index 0d5ddf5..ef8ace5 100644 --- a/clutter-gst/clutter-gst-camera.c +++ b/clutter-gst/clutter-gst-camera.c @@ -44,11 +44,9 @@ #include <gio/gio.h> #include <gst/base/gstbasesink.h> #include <gst/video/video.h> -#ifdef HAVE_GUDEV -#include <gudev/gudev.h> -#endif #include "clutter-gst-camera.h" +#include "clutter-gst-camera-manager.h" #include "clutter-gst-debug.h" #include "clutter-gst-enum-types.h" #include "clutter-gst-marshal.h" @@ -62,7 +60,6 @@ static const gchar *supported_media_types[] = { struct _ClutterGstCameraPrivate { - GPtrArray *camera_devices; ClutterGstCameraDevice *camera_device; ClutterGstFrame *current_frame; @@ -282,11 +279,7 @@ clutter_gst_camera_dispose (GObject *object) g_free (priv->photo_filename); priv->photo_filename = NULL; - if (priv->camera_devices) - { - g_ptr_array_unref (priv->camera_devices); - priv->camera_devices = NULL; - } + g_clear_object (&priv->camera_device); if (priv->bus) { @@ -676,107 +669,6 @@ set_device_resolutions (ClutterGstCamera *self, device_capture_resolution_changed (device, width, height, self); } -static void -add_device (ClutterGstCamera *self, - GstElementFactory *element_factory, - const gchar *device_node, - const gchar *device_name) -{ - ClutterGstCameraPrivate *priv = self->priv; - ClutterGstCameraDevice *device; - - if (!priv->camera_devices) - priv->camera_devices = - g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); - - device = g_object_new (CLUTTER_GST_TYPE_CAMERA_DEVICE, - "element-factory", element_factory, - "node", device_node, - "name", device_name, - NULL); - g_signal_connect (device, "capture-resolution-changed", - G_CALLBACK (device_capture_resolution_changed), - self); - g_ptr_array_add (priv->camera_devices, device); -} - -static gboolean -probe_camera_devices (ClutterGstCamera *self) -{ - ClutterGstCameraPrivate *priv = self->priv; - GstElement *videosrc; - GstElementFactory *element_factory; - GParamSpec *pspec; - gchar *device_node; - gchar *device_name; -#ifdef HAVE_GUDEV - GUdevClient *udev_client; - GList *udevices, *l; - GUdevDevice *udevice; -#endif - - videosrc = gst_element_factory_make ("v4l2src", "v4l2src"); - if (!videosrc) - { - g_warning ("Unable to get available camera devices, " - "v4l2src element missing"); - return FALSE; - } - - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (G_OBJECT (videosrc)), "device"); - if (!G_IS_PARAM_SPEC_STRING (pspec)) - { - g_warning ("Unable to get available camera devices, " - "v4l2src has no 'device' property"); - goto out; - } - - element_factory = gst_element_get_factory (videosrc); - -#ifdef HAVE_GUDEV - udev_client = g_udev_client_new (NULL); - udevices = g_udev_client_query_by_subsystem (udev_client, "video4linux"); - for (l = udevices; l != NULL; l = l->next) - { - gint v4l_version; - - udevice = (GUdevDevice *) l->data; - v4l_version = g_udev_device_get_property_as_int (udevice, "ID_V4L_VERSION"); - if (v4l_version == 2) - { - const char *caps; - - caps = g_udev_device_get_property (udevice, "ID_V4L_CAPABILITIES"); - if (caps == NULL || strstr (caps, ":capture:") == NULL) - continue; - - device_node = (gchar *) g_udev_device_get_device_file (udevice); - device_name = (gchar *) g_udev_device_get_property (udevice, "ID_V4L_PRODUCT"); - - add_device (self, element_factory, device_node, device_name); - } - - g_object_unref (udevice); - } - g_list_free (udevices); - g_object_unref (udev_client); -#else - /* GStreamer 1.0 does not support property probe, adding default detected - * device as only known device */ - g_object_get (videosrc, "device", &device_node, NULL); - g_object_get (videosrc, "device-name", &device_name, NULL); - add_device (self, element_factory, device_node, device_name); - - g_free (device_node); - g_free (device_name); -#endif - - out: - gst_object_unref (videosrc); - return (priv->camera_devices != NULL); -} - static gboolean setup_camera_source (ClutterGstCamera *self) { @@ -838,12 +730,8 @@ static gboolean setup_pipeline (ClutterGstCamera *self) { ClutterGstCameraPrivate *priv = self->priv; - - if (!probe_camera_devices (self)) - { - g_critical ("Unable to find any suitable capture device"); - return FALSE; - } + const GPtrArray *camera_devices = + clutter_gst_camera_manager_get_camera_devices (clutter_gst_camera_manager_get_default ()); priv->camerabin = gst_element_factory_make ("camerabin", "camerabin"); if (G_UNLIKELY (!priv->camerabin)) @@ -865,7 +753,7 @@ setup_pipeline (ClutterGstCamera *self) } if (!clutter_gst_camera_set_camera_device (self, - g_ptr_array_index (priv->camera_devices, 0))) + g_ptr_array_index (camera_devices, 0))) { g_critical ("Unable to select capture device"); gst_object_unref (priv->camerabin); @@ -977,23 +865,6 @@ clutter_gst_camera_new (void) /* } */ /** - * clutter_gst_camera_get_camera_devices: - * @self: a #ClutterGstCamera - * - * Retrieve an array of supported camera devices. - * - * Return value: (transfer none) (element-type ClutterGst.CameraDevice): An array of #ClutterGstCameraDevice representing - * the supported camera devices - */ -const GPtrArray * -clutter_gst_camera_get_camera_devices (ClutterGstCamera *self) -{ - g_return_val_if_fail (CLUTTER_GST_IS_CAMERA (self), NULL); - - return self->priv->camera_devices; -} - -/** * clutter_gst_camera_get_camera_device: * @self: a #ClutterGstCamera * @@ -1067,12 +938,24 @@ clutter_gst_camera_set_camera_device (ClutterGstCamera *self, gst_object_unref (element_factory); - priv->camera_device = device; + if (priv->camera_device) + { + g_signal_handlers_disconnect_by_func (priv->camera_device, + device_capture_resolution_changed, + self); + g_clear_object (&priv->camera_device); + } + + priv->camera_device = g_object_ref (device); g_object_set (G_OBJECT (src), "device", node, NULL); g_free (node); g_object_set (G_OBJECT (priv->camera_source), "video-source", src, NULL); + g_signal_connect (device, "capture-resolution-changed", + G_CALLBACK (device_capture_resolution_changed), + self); + set_device_resolutions (self, device); if (was_playing) diff --git a/clutter-gst/clutter-gst-camera.h b/clutter-gst/clutter-gst-camera.h index b3702a6..b18bc5c 100644 --- a/clutter-gst/clutter-gst-camera.h +++ b/clutter-gst/clutter-gst-camera.h @@ -116,8 +116,6 @@ GType clutter_gst_camera_get_type (void) G_GNUC_CONST; ClutterGstCamera * clutter_gst_camera_new (void); -const GPtrArray * - clutter_gst_camera_get_camera_devices (ClutterGstCamera *self); ClutterGstCameraDevice * clutter_gst_camera_get_camera_device (ClutterGstCamera *self); gboolean clutter_gst_camera_set_camera_device (ClutterGstCamera *self, diff --git a/clutter-gst/clutter-gst.h b/clutter-gst/clutter-gst.h index f6d2901..70b4ccc 100644 --- a/clutter-gst/clutter-gst.h +++ b/clutter-gst/clutter-gst.h @@ -34,6 +34,7 @@ #include "clutter-gst-enum-types.h" #include "clutter-gst-aspectratio.h" #include "clutter-gst-camera-device.h" +#include "clutter-gst-camera-manager.h" #include "clutter-gst-camera.h" #include "clutter-gst-content.h" #include "clutter-gst-crop.h" diff --git a/doc/reference/clutter-gst-sections.txt b/doc/reference/clutter-gst-sections.txt index 36af9c4..a37ac73 100644 --- a/doc/reference/clutter-gst-sections.txt +++ b/doc/reference/clutter-gst-sections.txt @@ -113,7 +113,6 @@ clutter_gst_camera_new clutter_gst_camera_get_brightness clutter_gst_camera_get_brightness_range clutter_gst_camera_get_camera_device -clutter_gst_camera_get_camera_devices clutter_gst_camera_get_color_balance_property clutter_gst_camera_get_color_balance_property_range clutter_gst_camera_get_contrast @@ -157,6 +156,25 @@ ClutterGstCameraPrivate </SECTION> <SECTION> +<FILE>clutter-gst-camera-manager</FILE> +<TITLE>ClutterGstCameraManager</TITLE> +ClutterGstCameraManager +ClutterGstCameraManagerClass +clutter_gst_camera_manager_get_camera_devices +clutter_gst_camera_manager_get_default +<SUBSECTION Standard> +CLUTTER_GST_CAMERA_MANAGER +CLUTTER_GST_CAMERA_MANAGER_CLASS +CLUTTER_GST_CAMERA_MANAGER_GET_CLASS +CLUTTER_GST_IS_CAMERA_MANAGER +CLUTTER_GST_IS_CAMERA_MANAGER_CLASS +CLUTTER_GST_TYPE_CAMERA_MANAGER +clutter_gst_camera_manager_get_type +<SUBSECTION Private> +ClutterGstCameraManagerPrivate +</SECTION> + +<SECTION> <FILE>clutter-gst-camera-device</FILE> <TITLE>ClutterGstCameraDevice</TITLE> ClutterGstCameraDevice diff --git a/examples/camera-player.c b/examples/camera-player.c index 4bd50a6..3aef99e 100644 --- a/examples/camera-player.c +++ b/examples/camera-player.c @@ -393,7 +393,7 @@ main (int argc, char *argv[]) NULL); - app->camera_devices = clutter_gst_camera_get_camera_devices (app->camera_player); + app->camera_devices = clutter_gst_camera_manager_get_camera_devices (clutter_gst_camera_manager_get_default ()); if (!app->camera_devices) { g_error ("no suitable camera device available"); |