summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2015-07-10 16:05:29 +0200
committerWim Taymans <wtaymans@redhat.com>2015-07-10 16:05:29 +0200
commit2f026995caef72381d1526fa923477cf52ee83eb (patch)
treeac41047e16994cdfaec2b05356b26d22a2cff112
parent88699b2fa0d9f23f13f51b2c461d099d239a0cf2 (diff)
device-monitor: port to GstDeviceMonitorGstDeviceMonitor
Use GstDeviceMonitor to monitor the GStreamer devices.
-rw-r--r--libcheese/cheese-camera-device-monitor.c305
-rw-r--r--libcheese/cheese-camera-device-monitor.h7
-rw-r--r--libcheese/cheese-camera-device.c269
-rw-r--r--libcheese/cheese-camera-device.h9
-rw-r--r--libcheese/cheese-camera.c141
-rw-r--r--libcheese/cheese-camera.h4
-rw-r--r--src/cheese-preferences.vala16
-rw-r--r--src/vapi/cheese-common.vapi17
-rw-r--r--tests/cheese-test-monitor.c6
9 files changed, 206 insertions, 568 deletions
diff --git a/libcheese/cheese-camera-device-monitor.c b/libcheese/cheese-camera-device-monitor.c
index 9ef64737..48520edb 100644
--- a/libcheese/cheese-camera-device-monitor.c
+++ b/libcheese/cheese-camera-device-monitor.c
@@ -26,46 +26,25 @@
#include <glib-object.h>
#include <string.h>
-#ifdef HAVE_UDEV
- #define G_UDEV_API_IS_SUBJECT_TO_CHANGE 1
- #include <gudev/gudev.h>
-#else
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #if USE_SYS_VIDEOIO_H > 0
- #include <sys/types.h>
- #include <sys/videoio.h>
- #elif defined (__sun)
- #include <sys/types.h>
- #include <sys/videodev2.h>
- #endif /* USE_SYS_VIDEOIO_H */
-#endif
-
#include "cheese-camera-device-monitor.h"
/**
* SECTION:cheese-camera-device-monitor
- * @short_description: Simple object to enumerate v4l devices
+ * @short_description: Simple object to enumerate video devices
* @stability: Unstable
* @include: cheese/cheese-camera-device-monitor.h
*
- * #CheeseCameraDeviceMonitor provides a basic interface for video4linux device
+ * #CheeseCameraDeviceMonitor provides a basic interface for video device
* enumeration and hotplugging.
*
- * It uses either GUdev or some platform specific code to list video devices.
- * It is also capable (right now in Linux only, with the udev backend) to
+ * It uses GstDeviceMonitor to list video devices. It is also capable to
* monitor device plugging and emit a CheeseCameraDeviceMonitor::added or
* CheeseCameraDeviceMonitor::removed signal when an event happens.
*/
struct _CheeseCameraDeviceMonitorPrivate
{
-#ifdef HAVE_UDEV
- GUdevClient *client;
-#else
- guint filler;
-#endif /* HAVE_UDEV */
+ GstDeviceMonitor *monitor;
};
G_DEFINE_TYPE_WITH_PRIVATE (CheeseCameraDeviceMonitor, cheese_camera_device_monitor, G_TYPE_OBJECT)
@@ -92,165 +71,100 @@ cheese_camera_device_monitor_error_quark (void)
return g_quark_from_static_string ("cheese-camera-error-quark");
}
-#ifdef HAVE_UDEV
-
/*
* cheese_camera_device_monitor_set_up_device:
- * @udevice: the device information from udev
+ * @device: the device information from GStreamer
*
- * Creates a new #CheeseCameraDevice for the supplied @udevice.
+ * Creates a new #CheeseCameraDevice for the supplied @device.
*
- * Returns: a new #CheeseCameraDevice, or %NULL if @udevice was not a V4L
- * capture device
+ * Returns: a new #CheeseCameraDevice, or %NULL if @device was not an
+ * acceptable capture device
*/
static CheeseCameraDevice*
-cheese_camera_device_monitor_set_up_device (GUdevDevice *udevice)
+cheese_camera_device_monitor_set_up_device (GstDevice *device)
{
- const char *device_file;
- const char *product_name;
- const char *vendor;
- const char *product;
- const char *bus;
- GError *error = NULL;
- gint vendor_id = 0;
- gint product_id = 0;
- gint v4l_version = 0;
- CheeseCameraDevice *device;
-
- const gchar *devpath = g_udev_device_get_property (udevice, "DEVPATH");
-
- GST_INFO ("Checking udev device '%s'", devpath);
-
- bus = g_udev_device_get_property (udevice, "ID_BUS");
- if (g_strcmp0 (bus, "usb") == 0)
- {
- vendor = g_udev_device_get_property (udevice, "ID_VENDOR_ID");
- if (vendor != NULL)
- vendor_id = g_ascii_strtoll (vendor, NULL, 16);
- product = g_udev_device_get_property (udevice, "ID_MODEL_ID");
- if (product != NULL)
- product_id = g_ascii_strtoll (product, NULL, 16);
- if (vendor_id == 0 || product_id == 0)
- {
- GST_WARNING ("Error getting vendor and product id");
- }
- else
- {
- GST_INFO ("Found device %04x:%04x, getting capabilities...", vendor_id, product_id);
- }
- }
- else
- {
- GST_INFO ("Not an usb device, skipping vendor and model id retrieval");
- }
+ CheeseCameraDevice *newdev;
+ GError *error = NULL;
- device_file = g_udev_device_get_device_file (udevice);
- if (device_file == NULL)
- {
- GST_WARNING ("Error getting V4L device");
- return NULL;
- }
+ newdev = cheese_camera_device_new (device, &error);
- /* vbi devices support capture capability too, but cannot be used,
- * so detect them by device name */
- if (strstr (device_file, "vbi"))
- {
- GST_INFO ("Skipping vbi device: %s", device_file);
- return NULL;
- }
-
- v4l_version = g_udev_device_get_property_as_int (udevice, "ID_V4L_VERSION");
- if (v4l_version == 2 || v4l_version == 1)
- {
- const char *caps;
-
- caps = g_udev_device_get_property (udevice, "ID_V4L_CAPABILITIES");
- if (caps == NULL || strstr (caps, ":capture:") == NULL)
- {
- GST_WARNING ("Device %s seems to not have the capture capability, (radio tuner?)"
- "Removing it from device list.", device_file);
- return NULL;
- }
- product_name = g_udev_device_get_property (udevice, "ID_V4L_PRODUCT");
- }
- else if (v4l_version == 0)
- {
- GST_ERROR ("Fix your udev installation to include v4l_id, ignoring %s", device_file);
- return NULL;
- }
- else
- {
- g_assert_not_reached ();
- }
-
- device = cheese_camera_device_new (devpath,
- device_file,
- product_name,
- v4l_version,
- &error);
-
- if (device == NULL)
- GST_WARNING ("Device initialization for %s failed: %s ",
- device_file,
+ if (newdev == NULL)
+ GST_WARNING ("Device initialization for %p failed: %s ",
+ device,
(error != NULL) ? error->message : "Unknown reason");
- return device;
+ return newdev;
}
/*
* cheese_camera_device_monitor_added:
* @monitor: a #CheeseCameraDeviceMonitor
- * @udevice: the device information, from udev, for the device that was added
+ * @device: the device information, from GStreamer, for the device that was added
*
* Emits the ::added signal.
*/
static void
cheese_camera_device_monitor_added (CheeseCameraDeviceMonitor *monitor,
- GUdevDevice *udevice)
+ GstDevice *device)
{
- CheeseCameraDevice *device = cheese_camera_device_monitor_set_up_device (udevice);
+ CheeseCameraDevice *newdev = cheese_camera_device_monitor_set_up_device (device);
/* Ignore non-video devices, GNOME bug #677544. */
- if (device)
- g_signal_emit (monitor, monitor_signals[ADDED], 0, device);
+ if (newdev) {
+ g_object_set_data (G_OBJECT (device), "cheese-camera-device", newdev);
+ g_signal_emit (monitor, monitor_signals[ADDED], 0, newdev);
+ }
}
/*
* cheese_camera_device_monitor_removed:
* @monitor: a #CheeseCameraDeviceMonitor
- * @udevice: the device information, from udev, for the device that was removed
+ * @device: the device information, from GStreamer, for the device that was removed
*
* Emits the ::removed signal.
*/
static void
cheese_camera_device_monitor_removed (CheeseCameraDeviceMonitor *monitor,
- GUdevDevice *udevice)
+ GstDevice *device)
{
- g_signal_emit (monitor, monitor_signals[REMOVED], 0,
- g_udev_device_get_property (udevice, "DEVPATH"));
+ CheeseCameraDevice *olddev;
+
+ olddev = g_object_get_data (G_OBJECT (device), "cheese-camera-device");
+ if (olddev)
+ g_signal_emit (monitor, monitor_signals[REMOVED], 0, olddev);
}
/*
- * cheese_camera_device_monitor_uevent_cb:
- * @client: a #GUdevClient
- * @action: the string representing the action type of the uevent
- * @udevice: the #GUdevDevice to which the uevent refers
- * @monitor: a #CheeseCameraDeviceMonitor
+ * cheese_camera_device_monitor_bus_func:
+ * @bus: a #GstBus
+ * @message: the message posted on the bus
*
- * Check if the uevent corresponds to device addition or removal, and if so,
+ * Check if the message corresponds to device addition or removal, and if so,
* pass it on to cheese_camera_device_monitor_added() or
* cheese_camera_device_monitor_removed() for emitting the ::added and
* ::removed signals.
*/
-static void
-cheese_camera_device_monitor_uevent_cb (GUdevClient *client,
- const gchar *action,
- GUdevDevice *udevice,
- CheeseCameraDeviceMonitor *monitor)
+static gboolean
+cheese_camera_device_monitor_bus_func (GstBus *bus,
+ GstMessage *message,
+ gpointer user_data)
{
- if (g_str_equal (action, "remove"))
- cheese_camera_device_monitor_removed (monitor, udevice);
- else if (g_str_equal (action, "add"))
- cheese_camera_device_monitor_added (monitor, udevice);
+ CheeseCameraDeviceMonitor *monitor = user_data;
+ GstDevice *device;
+
+ switch (GST_MESSAGE_TYPE (message))
+ {
+ case GST_MESSAGE_DEVICE_ADDED:
+ gst_message_parse_device_added (message, &device);
+ cheese_camera_device_monitor_added (monitor, device);
+ break;
+ case GST_MESSAGE_DEVICE_REMOVED:
+ gst_message_parse_device_removed (message, &device);
+ cheese_camera_device_monitor_removed (monitor, device);
+ break;
+ default:
+ break;
+ }
+ return G_SOURCE_CONTINUE;
}
/*
@@ -266,7 +180,7 @@ static void
cheese_camera_device_monitor_add_devices (gpointer data, gpointer user_data)
{
cheese_camera_device_monitor_added ((CheeseCameraDeviceMonitor *) user_data,
- (GUdevDevice *) data);
+ (GstDevice *) data);
g_object_unref (data);
}
@@ -288,11 +202,11 @@ cheese_camera_device_monitor_coldplug (CheeseCameraDeviceMonitor *monitor)
priv = cheese_camera_device_monitor_get_instance_private (monitor);
- g_return_if_fail (priv->client != NULL);
+ g_return_if_fail (priv->monitor != NULL);
- GST_INFO ("Probing devices with udev...");
+ GST_INFO ("Probing devices with GStreamer monitor...");
- devices = g_udev_client_query_by_subsystem (priv->client, "video4linux");
+ devices = gst_device_monitor_get_devices (priv->monitor);
if (devices == NULL) GST_WARNING ("No device found");
@@ -301,88 +215,16 @@ cheese_camera_device_monitor_coldplug (CheeseCameraDeviceMonitor *monitor)
g_list_free (devices);
}
-#else /* HAVE_UDEV */
-void
-cheese_camera_device_monitor_coldplug (CheeseCameraDeviceMonitor *monitor)
-{
- #if 0
- CheeseCameraDeviceMonitorPrivate *priv = monitor->priv;
- struct v4l2_capability v2cap;
- struct video_capability v1cap;
- int fd, ok;
-
- if ((fd = open (device_path, O_RDONLY | O_NONBLOCK)) < 0)
- {
- g_warning ("Failed to open %s: %s", device_path, strerror (errno));
- return;
- }
- ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap);
- if (ok < 0)
- {
- ok = ioctl (fd, VIDIOCGCAP, &v1cap);
- if (ok < 0)
- {
- g_warning ("Error while probing v4l capabilities for %s: %s",
- device_path, strerror (errno));
- close (fd);
- return;
- }
- g_print ("Detected v4l device: %s\n", v1cap.name);
- g_print ("Device type: %d\n", v1cap.type);
- gstreamer_src = "v4lsrc";
- product_name = v1cap.name;
- }
- else
- {
- guint cap = v2cap.capabilities;
- g_print ("Detected v4l2 device: %s\n", v2cap.card);
- g_print ("Driver: %s, version: %d\n", v2cap.driver, v2cap.version);
-
- /* g_print ("Bus info: %s\n", v2cap.bus_info); */ /* Doesn't seem anything useful */
- g_print ("Capabilities: 0x%08X\n", v2cap.capabilities);
- if (!(cap & V4L2_CAP_VIDEO_CAPTURE))
- {
- g_print ("Device %s seems to not have the capture capability, (radio tuner?)\n"
- "Removing it from device list.\n", device_path);
- close (fd);
- return;
- }
- gstreamer_src = "v4l2src";
- product_name = (char *) v2cap.card;
- }
- close (fd);
-
- GList *devices, *l;
-
- g_print ("Probing devices with udev...\n");
-
- if (priv->client == NULL)
- return;
-
- devices = g_udev_client_query_by_subsystem (priv->client, "video4linux");
-
- /* Initialize camera structures */
- for (l = devices; l != NULL; l = l->next)
- {
- cheese_camera_device_monitor_added (monitor, l->data);
- g_object_unref (l->data);
- }
- g_list_free (devices);
- #endif
-}
-
-#endif /* HAVE_UDEV */
-
static void
cheese_camera_device_monitor_finalize (GObject *object)
{
-#ifdef HAVE_UDEV
CheeseCameraDeviceMonitorPrivate *priv;
priv = cheese_camera_device_monitor_get_instance_private (CHEESE_CAMERA_DEVICE_MONITOR (object));
- g_clear_object (&priv->client);
-#endif /* HAVE_UDEV */
+ gst_device_monitor_stop (priv->monitor);
+ g_clear_object (&priv->monitor);
+
G_OBJECT_CLASS (cheese_camera_device_monitor_parent_class)->finalize (object);
}
@@ -416,7 +258,7 @@ cheese_camera_device_monitor_class_init (CheeseCameraDeviceMonitorClass *klass)
/**
* CheeseCameraDeviceMonitor::removed:
* @monitor: the #CheeseCameraDeviceMonitor that emitted the signal
- * @uuid: UUID for the device on the system
+ * @device: the #CheeseCameraDevice that was removed
*
* The ::removed signal is emitted when a camera is unplugged, or disabled on
* the system.
@@ -426,20 +268,27 @@ cheese_camera_device_monitor_class_init (CheeseCameraDeviceMonitorClass *klass)
G_STRUCT_OFFSET (CheeseCameraDeviceMonitorClass, removed),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
+ G_TYPE_NONE, 1, CHEESE_TYPE_CAMERA_DEVICE);
}
static void
cheese_camera_device_monitor_init (CheeseCameraDeviceMonitor *monitor)
{
-#ifdef HAVE_UDEV
CheeseCameraDeviceMonitorPrivate *priv = cheese_camera_device_monitor_get_instance_private (monitor);
- const gchar *const subsystems[] = {"video4linux", NULL};
+ GstBus *bus;
+ GstCaps *caps;
+
+ priv->monitor = gst_device_monitor_new ();
+
+ bus = gst_device_monitor_get_bus (priv->monitor);
+ gst_bus_add_watch (bus, cheese_camera_device_monitor_bus_func, monitor);
+ gst_object_unref (bus);
+
+ caps = gst_caps_new_empty_simple ("video/x-raw");
+ gst_device_monitor_add_filter (priv->monitor, "Video/Source", caps);
+ gst_caps_unref (caps);
- priv->client = g_udev_client_new (subsystems);
- g_signal_connect (G_OBJECT (priv->client), "uevent",
- G_CALLBACK (cheese_camera_device_monitor_uevent_cb), monitor);
-#endif /* HAVE_UDEV */
+ gst_device_monitor_start (priv->monitor);
}
/**
diff --git a/libcheese/cheese-camera-device-monitor.h b/libcheese/cheese-camera-device-monitor.h
index 1089000c..f11d0a4c 100644
--- a/libcheese/cheese-camera-device-monitor.h
+++ b/libcheese/cheese-camera-device-monitor.h
@@ -67,9 +67,10 @@ struct _CheeseCameraDeviceMonitorClass
GObjectClass parent_class;
/*< public >*/
- void (*added)(CheeseCameraDeviceMonitor *monitor,
- CheeseCameraDevice *device);
- void (*removed)(CheeseCameraDeviceMonitor *monitor, const gchar *uuid);
+ void (*added) (CheeseCameraDeviceMonitor *monitor,
+ CheeseCameraDevice *device);
+ void (*removed) (CheeseCameraDeviceMonitor *monitor,
+ CheeseCameraDevice *device);
};
GType cheese_camera_device_monitor_get_type (void);
diff --git a/libcheese/cheese-camera-device.c b/libcheese/cheese-camera-device.c
index f4ff19d6..d96f78d5 100644
--- a/libcheese/cheese-camera-device.c
+++ b/libcheese/cheese-camera-device.c
@@ -86,9 +86,7 @@ enum
{
PROP_0,
PROP_NAME,
- PROP_DEVICE_NODE,
- PROP_UUID,
- PROP_V4LAPI_VERSION,
+ PROP_DEVICE,
PROP_LAST
};
@@ -96,15 +94,12 @@ static GParamSpec *properties[PROP_LAST];
typedef struct
{
- gchar *device_node;
- gchar *uuid;
- const gchar *src;
- gchar *name;
- guint v4lapi_version;
- GstCaps *caps;
- GList *formats; /* list members are CheeseVideoFormatFull structs. */
+ GstDevice *device;
+ gchar *name;
+ GstCaps *caps;
+ GList *formats; /* list members are CheeseVideoFormatFull structs. */
- GError *construct_error;
+ GError *construct_error;
} CheeseCameraDevicePrivate;
G_DEFINE_TYPE_WITH_CODE (CheeseCameraDevice, cheese_camera_device,
@@ -520,101 +515,34 @@ cheese_camera_device_update_format_table (CheeseCameraDevice *device)
static void
cheese_camera_device_get_caps (CheeseCameraDevice *device)
{
- CheeseCameraDevicePrivate *priv;
- gchar *pipeline_desc;
- GstElement *pipeline;
- GstStateChangeReturn ret;
- GstMessage *msg;
- GstBus *bus;
- GError *err = NULL;
-
- priv = cheese_camera_device_get_instance_private (device);
- pipeline_desc = g_strdup_printf ("%s name=source device=%s ! fakesink",
- priv->src, priv->device_node);
- pipeline = gst_parse_launch (pipeline_desc, &err);
- if ((pipeline != NULL) && (err == NULL))
- {
- /* Start the pipeline and wait for max. 10 seconds for it to start up */
- gst_element_set_state (pipeline, GST_STATE_READY);
- ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
-
- /* Check if any error messages were posted on the bus */
- bus = gst_element_get_bus (pipeline);
- msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR);
- gst_object_unref (bus);
-
- if ((msg == NULL) && (ret == GST_STATE_CHANGE_SUCCESS))
- {
- GstElement *src;
- GstPad *pad;
- GstCaps *caps;
-
- src = gst_bin_get_by_name (GST_BIN (pipeline), "source");
+ CheeseCameraDevicePrivate *priv;
+ GstCaps *caps;
- GST_LOG ("Device: %s (%s)\n", priv->name, priv->device_node);
- pad = gst_element_get_static_pad (src, "src");
- caps = gst_pad_get_allowed_caps (pad);
+ priv = cheese_camera_device_get_instance_private (device);
- gst_caps_unref (priv->caps);
- priv->caps = cheese_camera_device_filter_caps (device, caps, supported_formats);
+ caps = gst_device_get_caps (priv->device);
+ if (caps == NULL)
+ caps = gst_caps_new_empty_simple ("video/x-raw");
- if (!gst_caps_is_empty (priv->caps))
- cheese_camera_device_update_format_table (device);
- else
- {
- g_set_error_literal (&priv->construct_error,
- CHEESE_CAMERA_DEVICE_ERROR,
- CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS,
- _("Device capabilities not supported"));
- }
+ gst_caps_unref (priv->caps);
+ priv->caps = cheese_camera_device_filter_caps (device, caps, supported_formats);
- gst_object_unref (pad);
- gst_caps_unref (caps);
- gst_object_unref (src);
- }
- else
- {
- if (msg)
- {
- gchar *dbg_info = NULL;
- gst_message_parse_error (msg, &err, &dbg_info);
- GST_WARNING ("Failed to start the capability probing pipeline");
- GST_WARNING ("Error from element %s: %s, %s",
- GST_OBJECT_NAME (msg->src),
- err->message,
- (dbg_info) ? dbg_info : "no extra debug detail");
- g_error_free (err);
- err = NULL;
-
- /* construct_error is meant to be displayed in the UI
- * (although it currently isn't displayed in cheese),
- * err->message from gstreamer is too technical for this
- * purpose, the idea is warn the user about an error and point
- * him to the logs for more info */
- g_set_error (&priv->construct_error,
- CHEESE_CAMERA_DEVICE_ERROR,
- CHEESE_CAMERA_DEVICE_ERROR_FAILED_INITIALIZATION,
- _("Failed to initialize device %s for capability probing"),
- priv->device_node);
- }
- }
- gst_element_set_state (pipeline, GST_STATE_NULL);
- gst_object_unref (pipeline);
+ if (!gst_caps_is_empty (priv->caps))
+ cheese_camera_device_update_format_table (device);
+ else
+ {
+ g_set_error_literal (&priv->construct_error,
+ CHEESE_CAMERA_DEVICE_ERROR,
+ CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS,
+ _("Device capabilities not supported"));
}
-
- if (err)
- g_error_free (err);
-
- g_free (pipeline_desc);
+ gst_caps_unref (caps);
}
static void
cheese_camera_device_constructed (GObject *object)
{
CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (object);
- CheeseCameraDevicePrivate *priv = cheese_camera_device_get_instance_private (device);
-
- priv->src = (priv->v4lapi_version == 2) ? "v4l2src" : "v4lsrc";
cheese_camera_device_get_caps (device);
@@ -633,14 +561,8 @@ cheese_camera_device_get_property (GObject *object, guint prop_id, GValue *value
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
- case PROP_DEVICE_NODE:
- g_value_set_string (value, priv->device_node);
- break;
- case PROP_UUID:
- g_value_set_string (value, priv->uuid);
- break;
- case PROP_V4LAPI_VERSION:
- g_value_set_uint (value, priv->v4lapi_version);
+ case PROP_DEVICE:
+ g_value_set_object (value, priv->device);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -657,22 +579,15 @@ cheese_camera_device_set_property (GObject *object, guint prop_id, const GValue
switch (prop_id)
{
case PROP_NAME:
- if (priv->name)
- g_free (priv->name);
+ g_free (priv->name);
priv->name = g_value_dup_string (value);
break;
- case PROP_UUID:
- if (priv->uuid)
- g_free (priv->uuid);
- priv->uuid = g_value_dup_string (value);
- break;
- case PROP_DEVICE_NODE:
- if (priv->device_node)
- g_free (priv->device_node);
- priv->device_node = g_value_dup_string (value);
- break;
- case PROP_V4LAPI_VERSION:
- priv->v4lapi_version = g_value_get_uint (value);
+ case PROP_DEVICE:
+ if (priv->device)
+ g_object_unref (priv->device);
+ priv->device = g_value_dup_object (value);
+ g_free (priv->name);
+ priv->name = gst_device_get_display_name (priv->device);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -686,8 +601,7 @@ cheese_camera_device_finalize (GObject *object)
CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (object);
CheeseCameraDevicePrivate *priv = cheese_camera_device_get_instance_private (device);
- g_free (priv->device_node);
- g_free (priv->uuid);
+ g_object_unref (priv->device);
g_free (priv->name);
gst_caps_unref (priv->caps);
@@ -725,44 +639,17 @@ cheese_camera_device_class_init (CheeseCameraDeviceClass *klass)
G_PARAM_STATIC_STRINGS);
/**
- * CheeseCameraDevice:device-node:
+ * CheeseCameraDevice:device:
*
- * Path to the device node of the video capture device.
+ * GStreamer device object of the video capture device.
*/
- properties[PROP_DEVICE_NODE] = g_param_spec_string ("device-node",
- "Device node",
- "Path to the device node of the video capture device",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- /**
- * CheeseCameraDevice:uuid:
- *
- * UUID of the video capture device.
- */
- properties[PROP_UUID] = g_param_spec_string ("uuid",
- "Device UUID",
- "UUID of the video capture device",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- /**
- * CheeseCameraDevice:v4l-api-version:
- *
- * Version of the Video4Linux API that the device supports. Currently, either
- * 1 or 2 are supported.
- */
- properties[PROP_V4LAPI_VERSION] = g_param_spec_uint ("v4l-api-version",
- "Video4Linux API version",
- "Version of the Video4Linux API that the device supports",
- 1, 2, 2,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
+ properties[PROP_DEVICE] = g_param_spec_object ("device",
+ "Device",
+ "The GStreamer device object of the video capture device",
+ GST_TYPE_DEVICE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST, properties);
}
@@ -815,32 +702,21 @@ cheese_camera_device_initable_init (GInitable *initable,
/**
* cheese_camera_device_new:
- * @uuid: UUID of the device, as supplied by udev
- * @device_node: (type filename): path to the device node of the video capture
- * device
- * @name: human-readable name of the device, as supplied by udev
- * @v4l_api_version: version of the Video4Linux API that the device uses. Currently
- * either 1 or 2
+ * @device: The GStreamer the device, as supplied by GstDeviceMonitor
* @error: a location to store errors
*
- * Tries to create a new #CheeseCameraDevice with the supplied parameters. If
+ * Tries to create a new #CheeseCameraDevice with the supplied device. If
* construction fails, %NULL is returned, and @error is set.
*
* Returns: a new #CheeseCameraDevice, or %NULL
*/
CheeseCameraDevice *
-cheese_camera_device_new (const gchar *uuid,
- const gchar *device_node,
- const gchar *name,
- guint v4l_api_version,
- GError **error)
+cheese_camera_device_new (GstDevice *device,
+ GError **error)
{
return CHEESE_CAMERA_DEVICE (g_initable_new (CHEESE_TYPE_CAMERA_DEVICE,
NULL, error,
- "uuid", uuid,
- "device-node", device_node,
- "name", name,
- "v4l-api-version", v4l_api_version,
+ "device", device,
NULL));
}
@@ -887,36 +763,14 @@ cheese_camera_device_get_name (CheeseCameraDevice *device)
}
/**
- * cheese_camera_device_get_uuid:
- * @device: a #CheeseCameraDevice
- *
- * Get the UUID of the @device, as reported by udev.
- *
- * Returns: (transfer none): the UUID of the video capture device
- */
-const gchar *
-cheese_camera_device_get_uuid (CheeseCameraDevice *device)
-{
- CheeseCameraDevicePrivate *priv;
-
- g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device), NULL);
-
- priv = cheese_camera_device_get_instance_private (device);
-
- return priv->uuid;
-}
-
-/**
* cheese_camera_device_get_src:
* @device: a #CheeseCameraDevice
*
- * Get the name of the source GStreamer element for the @device. Currently,
- * this will be either v4lsrc or v4l2src, depending on the version of the
- * Video4Linux API that the device supports.
+ * Get the source GStreamer element for the @device.
*
- * Returns: (transfer none): the name of the source GStreamer element
+ * Returns: (transfer full): the source GStreamer element
*/
-const gchar *
+GstElement *
cheese_camera_device_get_src (CheeseCameraDevice *device)
{
CheeseCameraDevicePrivate *priv;
@@ -925,28 +779,7 @@ cheese_camera_device_get_src (CheeseCameraDevice *device)
priv = cheese_camera_device_get_instance_private (device);
- return priv->src;
-}
-
-/**
- * cheese_camera_device_get_device_node:
- * @device: a #CheeseCameraDevice
- *
- * Get the path to the device node associated with the @device.
- *
- * Returns: (transfer none): the path to the device node of the video capture
- * device
- */
-const gchar *
-cheese_camera_device_get_device_node (CheeseCameraDevice *device)
-{
- CheeseCameraDevicePrivate *priv;
-
- g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (device), NULL);
-
- priv = cheese_camera_device_get_instance_private (device);
-
- return priv->device_node;
+ return gst_device_create_element (priv->device, NULL);
}
/**
diff --git a/libcheese/cheese-camera-device.h b/libcheese/cheese-camera-device.h
index 45904611..4f5d819f 100644
--- a/libcheese/cheese-camera-device.h
+++ b/libcheese/cheese-camera-device.h
@@ -64,10 +64,7 @@ GType cheese_video_format_get_type (void);
#define CHEESE_TYPE_CAMERA_DEVICE (cheese_camera_device_get_type ())
G_DECLARE_FINAL_TYPE (CheeseCameraDevice, cheese_camera_device, CHEESE, CAMERA_DEVICE, GObject)
-CheeseCameraDevice *cheese_camera_device_new (const gchar *uuid,
- const gchar *device_node,
- const gchar *name,
- guint v4l_api_version,
+CheeseCameraDevice *cheese_camera_device_new (GstDevice *device,
GError **error);
GstCaps *cheese_camera_device_get_caps_for_format (CheeseCameraDevice *device,
@@ -76,9 +73,7 @@ CheeseVideoFormat *cheese_camera_device_get_best_format (CheeseCameraDevice *dev
GList * cheese_camera_device_get_format_list (CheeseCameraDevice *device);
const gchar *cheese_camera_device_get_name (CheeseCameraDevice *device);
-const gchar *cheese_camera_device_get_src (CheeseCameraDevice *device);
-const gchar *cheese_camera_device_get_uuid (CheeseCameraDevice *device);
-const gchar *cheese_camera_device_get_device_node (CheeseCameraDevice *device);
+GstElement * cheese_camera_device_get_src (CheeseCameraDevice *device);
G_END_DECLS
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index f15f2163..095636b2 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -84,7 +84,7 @@ struct _CheeseCameraPrivate
gchar *photo_filename;
guint num_camera_devices;
- gchar *device_node;
+ CheeseCameraDevice *device;
/* an array of CheeseCameraDevices */
GPtrArray *camera_devices;
@@ -106,7 +106,7 @@ enum
{
PROP_0,
PROP_VIDEO_TEXTURE,
- PROP_DEVICE_NODE,
+ PROP_DEVICE,
PROP_FORMAT,
PROP_NUM_CAMERA_DEVICES,
PROP_LAST
@@ -312,34 +312,23 @@ cheese_camera_add_device (CheeseCameraDeviceMonitor *monitor,
/*
* cheese_camera_remove_device:
* @monitor: a #CheeseCameraDeviceMonitor
- * @uuid: UUId of a #CheeseCameraDevice
+ * @device: a #CheeseCameraDevice
* @camera: a #CheeseCamera
*
* Handle the CheeseCameraDeviceMonitor::removed signal and remove the
- * #CheeseCameraDevice associated with the UUID from the list of current
- * devices.
+ * #CheeseCameraDevice from the list of current devices.
*/
static void
cheese_camera_remove_device (CheeseCameraDeviceMonitor *monitor,
- const gchar *uuid,
+ CheeseCameraDevice *device,
CheeseCamera *camera)
{
- guint i;
-
- CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
+ CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
- for (i = 0; i < priv->num_camera_devices; i++)
+ if (g_ptr_array_remove (priv->camera_devices, (gpointer) device))
{
- CheeseCameraDevice *device = (CheeseCameraDevice *) g_ptr_array_index (priv->camera_devices, i);
- const gchar *device_uuid = cheese_camera_device_get_uuid (device);
-
- if (strcmp (device_uuid, uuid) == 0)
- {
- g_ptr_array_remove (priv->camera_devices, (gpointer) device);
- priv->num_camera_devices--;
- g_object_notify_by_pspec (G_OBJECT (camera), properties[PROP_NUM_CAMERA_DEVICES]);
- break;
- }
+ priv->num_camera_devices--;
+ g_object_notify_by_pspec (G_OBJECT (camera), properties[PROP_NUM_CAMERA_DEVICES]);
}
}
@@ -381,45 +370,48 @@ cheese_camera_set_camera_source (CheeseCamera *camera)
{
CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
- GError *err = NULL;
- gchar *camera_input;
-
- guint i;
+ guint i;
CheeseCameraDevice *selected_camera;
+ GstElement *src, *filter;
+ GstPad *srcpad;
if (priv->video_source)
gst_object_unref (priv->video_source);
/* If we have a matching video device use that one, otherwise use the first */
priv->selected_device = 0;
- selected_camera = g_ptr_array_index (priv->camera_devices, 0);
+ selected_camera = g_ptr_array_index (priv->camera_devices, 0);
for (i = 1; i < priv->num_camera_devices; i++)
{
- CheeseCameraDevice *device = g_ptr_array_index (priv->camera_devices, i);
- if (g_strcmp0 (cheese_camera_device_get_device_node (device),
- priv->device_node) == 0)
+ CheeseCameraDevice *dev = g_ptr_array_index (priv->camera_devices, i);
+ if (dev == priv->device)
{
- selected_camera = device;
+ selected_camera = dev;
priv->selected_device = i;
break;
}
}
- camera_input = g_strdup_printf (
- "%s name=video_source device=%s ! capsfilter name=video_source_filter",
- cheese_camera_device_get_src (selected_camera),
- cheese_camera_device_get_device_node (selected_camera));
-
- priv->video_source = gst_parse_bin_from_description (camera_input, TRUE, &err);
- g_free (camera_input);
-
+ priv->video_source = gst_bin_new (NULL);
if (priv->video_source == NULL)
{
- g_clear_error(&err);
return FALSE;
}
+ src = cheese_camera_device_get_src (selected_camera);
+ gst_bin_add (GST_BIN (priv->video_source), src);
+
+ filter = gst_element_factory_make ("capsfilter", "video_source_filter");
+ gst_bin_add (GST_BIN (priv->video_source), filter);
+
+ gst_element_link (src, filter);
+
+ srcpad = gst_element_get_static_pad (filter, "src");
+ gst_element_add_pad (priv->video_source,
+ gst_ghost_pad_new ("src", srcpad));
+ gst_object_unref (srcpad);
+
return TRUE;
}
@@ -1270,7 +1262,7 @@ cheese_camera_finalize (GObject *object)
if (priv->photo_filename)
g_free (priv->photo_filename);
g_free (priv->current_effect_desc);
- g_free (priv->device_node);
+ g_object_unref (priv->device);
g_boxed_free (CHEESE_TYPE_VIDEO_FORMAT, priv->current_format);
/* Free CheeseCameraDevice array */
@@ -1296,8 +1288,8 @@ cheese_camera_get_property (GObject *object, guint prop_id, GValue *value,
case PROP_VIDEO_TEXTURE:
g_value_set_pointer (value, priv->video_texture);
break;
- case PROP_DEVICE_NODE:
- g_value_set_string (value, priv->device_node);
+ case PROP_DEVICE:
+ g_value_set_object (value, priv->device);
break;
case PROP_FORMAT:
g_value_set_boxed (value, priv->current_format);
@@ -1326,9 +1318,9 @@ cheese_camera_set_property (GObject *object, guint prop_id, const GValue *value,
case PROP_VIDEO_TEXTURE:
priv->video_texture = g_value_get_pointer (value);
break;
- case PROP_DEVICE_NODE:
- g_free (priv->device_node);
- priv->device_node = g_value_dup_string (value);
+ case PROP_DEVICE:
+ g_object_unref (priv->device);
+ priv->device = g_value_dup_object (value);
break;
case PROP_FORMAT:
if (priv->current_format != NULL)
@@ -1422,16 +1414,16 @@ cheese_camera_class_init (CheeseCameraClass *klass)
G_PARAM_STATIC_STRINGS);
/**
- * CheeseCamera:device-node:
+ * CheeseCamera:device:
*
- * The path to the device node for the video capture device.
+ * The device object to capture from.
*/
- properties[PROP_DEVICE_NODE] = g_param_spec_string ("device-node",
- "Device node",
- "The path to the device node for the video capture device",
- "",
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS);
+ properties[PROP_DEVICE] = g_param_spec_object ("device",
+ "Device",
+ "The device object to capture from",
+ CHEESE_TYPE_CAMERA_DEVICE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
/**
* CheeseCamera:format:
@@ -1506,57 +1498,30 @@ cheese_camera_new (ClutterTexture *video_texture, const gchar *camera_device_nod
}
/**
- * cheese_camera_set_device_by_device_node:
+ * cheese_camera_set_device:
* @camera: a #CheeseCamera
- * @file: (type filename): the device node path
+ * @device: the device object
*
- * Set the active video capture device of the @camera, matching by device node
- * path.
+ * Set the active video capture device of the @camera.
*/
void
-cheese_camera_set_device_by_device_node (CheeseCamera *camera, const gchar *file)
+cheese_camera_set_device (CheeseCamera *camera, CheeseCameraDevice *device)
{
g_return_if_fail (CHEESE_IS_CAMERA (camera));
- g_object_set (camera, "device-node", file, NULL);
-}
-
-/*
- * cheese_camera_set_device_by_uuid:
- * @camera: a #CheeseCamera
- * @uuid: UUID of a #CheeseCameraDevice
- *
- * Set the active video capture device of the @camera, matching by UUID.
- */
-static void
-cheese_camera_set_device_by_dev_uuid (CheeseCamera *camera, const gchar *uuid)
-{
- CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
- guint i;
-
- for (i = 0; i < priv->num_camera_devices; i++)
- {
- CheeseCameraDevice *device = g_ptr_array_index (priv->camera_devices, i);
- if (strcmp (cheese_camera_device_get_uuid (device), uuid) == 0)
- {
- g_object_set (camera,
- "device-node", cheese_camera_device_get_uuid (device),
- NULL);
- break;
- }
- }
+ g_object_set (camera, "device", device, NULL);
}
/**
* cheese_camera_setup:
* @camera: a #CheeseCamera
- * @uuid: (allow-none): UUID of the video capture device, or %NULL
+ * @device: (allow-none): the video capture device, or %NULL
* @error: return location for a #GError, or %NULL
*
* Setup a video capture device.
*/
void
-cheese_camera_setup (CheeseCamera *camera, const gchar *uuid, GError **error)
+cheese_camera_setup (CheeseCamera *camera, CheeseCameraDevice *device, GError **error)
{
CheeseCameraPrivate *priv;
GError *tmp_error = NULL;
@@ -1575,9 +1540,9 @@ cheese_camera_setup (CheeseCamera *camera, const gchar *uuid, GError **error)
return;
}
- if (uuid != NULL)
+ if (device != NULL)
{
- cheese_camera_set_device_by_dev_uuid (camera, uuid);
+ cheese_camera_set_device (camera, device);
}
diff --git a/libcheese/cheese-camera.h b/libcheese/cheese-camera.h
index bbad2bd1..cd69a9ec 100644
--- a/libcheese/cheese-camera.h
+++ b/libcheese/cheese-camera.h
@@ -101,7 +101,7 @@ CheeseCamera *cheese_camera_new (ClutterTexture *video_texture,
gint y_resolution);
const CheeseVideoFormat *cheese_camera_get_current_video_format (CheeseCamera *camera);
-void cheese_camera_setup (CheeseCamera *camera, const gchar *uuid, GError **error);
+void cheese_camera_setup (CheeseCamera *camera, CheeseCameraDevice *device, GError **error);
void cheese_camera_play (CheeseCamera *camera);
void cheese_camera_stop (CheeseCamera *camera);
void cheese_camera_set_effect (CheeseCamera *camera, CheeseEffect *effect);
@@ -114,7 +114,7 @@ gboolean cheese_camera_take_photo (CheeseCamera *camera, const gchar
gboolean cheese_camera_take_photo_pixbuf (CheeseCamera *camera);
CheeseCameraDevice *cheese_camera_get_selected_device (CheeseCamera *camera);
GPtrArray * cheese_camera_get_camera_devices (CheeseCamera *camera);
-void cheese_camera_set_device_by_device_node (CheeseCamera *camera, const gchar *file);
+void cheese_camera_set_device (CheeseCamera *camera, CheeseCameraDevice *device);
void cheese_camera_switch_camera_device (CheeseCamera *camera);
GList * cheese_camera_get_video_formats (CheeseCamera *camera);
void cheese_camera_set_video_format (CheeseCamera *camera,
diff --git a/src/cheese-preferences.vala b/src/cheese-preferences.vala
index 21b68f38..8a3eb7ea 100644
--- a/src/cheese-preferences.vala
+++ b/src/cheese-preferences.vala
@@ -108,7 +108,7 @@ public PreferencesDialog (Cheese.Camera camera)
devices.foreach(add_camera_device);
- settings.set_string ("camera", camera.get_selected_device ().get_device_node ());
+ settings.set_string ("camera", camera.get_selected_device ().get_name ());
setup_resolutions_for_device (camera.get_selected_device ());
}
@@ -196,10 +196,10 @@ public PreferencesDialog (Cheese.Camera camera)
combo.get_active_iter (out iter);
combo.model.get (iter, 1, out dev);
- camera.set_device_by_device_node (dev.get_device_node ());
+ camera.set_device (dev);
camera.switch_camera_device ();
setup_resolutions_for_device (camera.get_selected_device ());
- settings.set_string ("camera", dev.get_device_node ());
+ settings.set_string ("camera", dev.get_name ());
}
/**
@@ -387,7 +387,7 @@ public PreferencesDialog (Cheese.Camera camera)
camera_model.get (iter, 1, out new_device, -1);
// Found the device that was removed.
- if (strcmp (old_device.device_node, new_device.device_node) != 0)
+ if (old_device != new_device)
{
remove_camera_device (iter, new_device, active_device);
device_removed = true;
@@ -406,7 +406,7 @@ public PreferencesDialog (Cheese.Camera camera)
}
}
- settings.set_string ("camera", camera.get_selected_device ().get_device_node ());
+ settings.set_string ("camera", camera.get_selected_device ().get_name ());
setup_resolutions_for_device (camera.get_selected_device ());
}
@@ -425,10 +425,10 @@ public PreferencesDialog (Cheese.Camera camera)
camera_model.append (out iter);
camera_model.set (iter,
- 0, dev.get_name () + " (" + dev.get_device_node () + ")",
+ 0, dev.get_name (),
1, dev);
- if (camera.get_selected_device ().get_device_node () == dev.get_device_node ())
+ if (camera.get_selected_device () == dev)
source_combo.set_active_iter (iter);
if (camera_model.iter_n_children (null) > 1)
@@ -448,7 +448,7 @@ public PreferencesDialog (Cheese.Camera camera)
unowned GLib.PtrArray devices = camera.get_camera_devices ();
// Check if the camera that we want to remove, is the active one
- if (strcmp (device_node.device_node, active_device_node.device_node) == 0)
+ if (device_node == active_device_node)
{
if (devices.len > 0)
set_new_available_camera_device (iter);
diff --git a/src/vapi/cheese-common.vapi b/src/vapi/cheese-common.vapi
index a926725b..702d7012 100644
--- a/src/vapi/cheese-common.vapi
+++ b/src/vapi/cheese-common.vapi
@@ -43,8 +43,7 @@ namespace Cheese
public bool has_camera ();
public void play ();
public void set_balance_property (string property, double value);
- public void set_device_by_device_node (string file);
- public void set_device_by_uuid (string uuid);
+ public void set_device (Cheese.CameraDevice device);
public void set_effect (Cheese.Effect effect);
public void toggle_effects_pipeline (bool active);
public void connect_effect_texture (Cheese.Effect effect, Clutter.Texture texture);
@@ -77,17 +76,13 @@ namespace Cheese
public CameraDevice (string uuid, string device_node, string name, int v4lapi_version) throws GLib.Error;
public Cheese.VideoFormat get_best_format ();
public Gst.Caps get_caps_for_format (Cheese.VideoFormat format);
- public unowned string get_device_node ();
public GLib.List<unowned Cheese.VideoFormat> get_format_list ();
- public unowned string get_uuid ();
public unowned string get_name ();
- public unowned string get_src ();
+ public Gst.Element get_src ();
[NoAccessorMethod]
- public uint v4l_api_version {get; construct;}
- public string device_node {get; construct;}
+ public Gst.Device device {get; construct;}
[NoAccessorMethod]
- public string uuid {owned get; construct;}
- public string name {get; construct;}
+ public string name {get;}
}
[CCode (cheader_filename = "cheese-camera-device-monitor.h")]
@@ -96,8 +91,8 @@ namespace Cheese
[CCode (has_construct_function = false)]
public CameraDeviceMonitor ();
public void coldplug ();
- public virtual signal void added (string uuid, string device_file, string product_name, uint api_version);
- public virtual signal void removed (string id);
+ public virtual signal void added (Gst.Device device);
+ public virtual signal void removed (Gst.Device device);
}
diff --git a/tests/cheese-test-monitor.c b/tests/cheese-test-monitor.c
index 1afb871a..e2b99170 100644
--- a/tests/cheese-test-monitor.c
+++ b/tests/cheese-test-monitor.c
@@ -10,16 +10,16 @@ added_cb (CheeseCameraDeviceMonitor *monitor,
CheeseCameraDevice *device,
gpointer user_data)
{
- g_message ("Added new device with ID '%s'", cheese_camera_device_get_uuid (device));
+ g_message ("Added new device with name '%s'", cheese_camera_device_get_name (device));
g_object_unref (device);
}
static void
removed_cb (CheeseCameraDeviceMonitor *monitor,
- const gchar *uuid,
+ const gchar *name,
gpointer user_data)
{
- g_message ("Removed device with ID '%s'", uuid);
+ g_message ("Removed device with name '%s'", name);
}
int