From b39f653c3d6ac9d41120d32b89ad21ccfbffde65 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 7 Nov 2003 12:45:20 +0000 Subject: [PATCH] Add device autodetection Original commit message from CVS: Add device autodetection --- sys/v4l/gstv4lelement.c | 169 ++++++++++++++++++++++++++++++++++++++++ sys/v4l/gstv4lelement.h | 5 ++ 2 files changed, 174 insertions(+) diff --git a/sys/v4l/gstv4lelement.c b/sys/v4l/gstv4lelement.c index 4b106581a0..5a2308ef41 100644 --- a/sys/v4l/gstv4lelement.c +++ b/sys/v4l/gstv4lelement.c @@ -21,12 +21,19 @@ #include #endif +#include +#include +#include +#include + #include #include "v4l_calls.h" #include "gstv4ltuner.h" #include "gstv4lxoverlay.h" #include "gstv4lcolorbalance.h" +#include + /* elementfactory information */ static GstElementDetails gst_v4lelement_details = GST_ELEMENT_DETAILS ( "Generic video4linux Element", @@ -97,6 +104,156 @@ gst_v4l_interface_init (GstInterfaceClass *klass) klass->supported = gst_v4l_iface_supported; } +static const GList * +gst_v4l_probe_get_properties (GstPropertyProbe *probe) +{ + GObjectClass *klass = G_OBJECT_GET_CLASS (probe); + static GList *list = NULL; + + if (!list) { + list = g_list_append (NULL, g_object_class_find_property (klass, "device")); + } + + return list; +} + +static gboolean +gst_v4l_class_probe_devices (GstV4lElementClass *klass, + gboolean check) +{ + static gboolean init = FALSE; + + if (!init && !check) { + gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL }; + gint base, n, fd; + + while (klass->devices) { + GList *item = klass->devices; + gchar *device = item->data; + + klass->devices = g_list_remove (klass->devices, item); + g_free (device); + } + + /* detect /dev entries */ + for (n = 0; n < 64; n++) { + for (base = 0; dev_base[base] != NULL; base++) { + struct stat s; + gchar *device = g_strdup_printf ("%s%d", dev_base[base], n); + + /* does the /dev/ entry exist at all? */ + if (stat (device, &s) == 0) { + /* yes: is a device attached? */ + if ((fd = open (device, O_RDONLY)) > 0 || errno == EBUSY) { + if (fd > 0) + close (fd); + + klass->devices = g_list_append (klass->devices, device); + break; + } + } + g_free (device); + } + } + + init = TRUE; + } + + return init; +} + +static void +gst_v4l_probe_probe_property (GstPropertyProbe *probe, + guint prop_id, + const GParamSpec *pspec) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe); + + switch (prop_id) { + case ARG_DEVICE: + gst_v4l_class_probe_devices (klass, FALSE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } +} + +static gboolean +gst_v4l_probe_needs_probe (GstPropertyProbe *probe, + guint prop_id, + const GParamSpec *pspec) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe); + gboolean ret = FALSE; + + switch (prop_id) { + case ARG_DEVICE: + ret = !gst_v4l_class_probe_devices (klass, TRUE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return ret; +} + +static GValueArray * +gst_v4l_class_list_devices (GstV4lElementClass *klass) +{ + GValueArray *array; + GValue value = { 0 }; + GList *item; + + if (!klass->devices) + return NULL; + + array = g_value_array_new (g_list_length (klass->devices)); + item = klass->devices; + g_value_init (&value, G_TYPE_STRING); + while (item) { + gchar *device = item->data; + + g_value_set_string (&value, device); + g_value_array_append (array, &value); + + item = item->next; + } + g_value_unset (&value); + + return array; +} + +static GValueArray * +gst_v4l_probe_get_values (GstPropertyProbe *probe, + guint prop_id, + const GParamSpec *pspec) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe); + GValueArray *array = NULL; + + switch (prop_id) { + case ARG_DEVICE: + array = gst_v4l_class_list_devices (klass); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return array; +} + +static void +gst_v4l_property_probe_interface_init (GstPropertyProbeInterface *iface) +{ + iface->get_properties = gst_v4l_probe_get_properties; + iface->probe_property = gst_v4l_probe_probe_property; + iface->needs_probe = gst_v4l_probe_needs_probe; + iface->get_values = gst_v4l_probe_get_values; +} + #define GST_TYPE_V4L_DEVICE_FLAGS (gst_v4l_device_get_type ()) GType gst_v4l_device_get_type (void) @@ -162,6 +319,11 @@ gst_v4lelement_get_type (void) NULL, NULL, }; + static const GInterfaceInfo v4l_propertyprobe_info = { + (GInterfaceInitFunc) gst_v4l_property_probe_interface_init, + NULL, + NULL, + }; v4lelement_type = g_type_register_static(GST_TYPE_ELEMENT, "GstV4lElement", @@ -179,6 +341,9 @@ gst_v4lelement_get_type (void) g_type_add_interface_static (v4lelement_type, GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info); + g_type_add_interface_static (v4lelement_type, + GST_TYPE_PROPERTY_PROBE, + &v4l_propertyprobe_info); } return v4lelement_type; @@ -189,9 +354,13 @@ static void gst_v4lelement_base_init (gpointer g_class) { GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class); + + klass->devices = NULL; gst_element_class_set_details (gstelement_class, &gst_v4lelement_details); } + static void gst_v4lelement_class_init (GstV4lElementClass *klass) { diff --git a/sys/v4l/gstv4lelement.h b/sys/v4l/gstv4lelement.h index 45a5d424f3..1b13c79ef7 100644 --- a/sys/v4l/gstv4lelement.h +++ b/sys/v4l/gstv4lelement.h @@ -52,6 +52,8 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LELEMENT)) #define GST_IS_V4LELEMENT_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LELEMENT)) +#define GST_V4LELEMENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_V4LELEMENT, GstV4lElementClass)) typedef struct _GstV4lElement GstV4lElement; typedef struct _GstV4lElementClass GstV4lElementClass; @@ -90,6 +92,9 @@ struct _GstV4lElement { struct _GstV4lElementClass { GstElementClass parent_class; + /* probed devices */ + GList *devices; + /* signals */ void (*open) (GstElement *element, const gchar *device);