Unification of the way to speak to v4l2 and v4l elements... Also fix a segfautl when...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sun, 2 Mar 2003 21:58:52 +0000 (21:58 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sun, 2 Mar 2003 21:58:52 +0000 (21:58 +0000)
Original commit message from CVS:
Unification of the way to speak to v4l2 and v4l elements... Also fix a segfautl when doing gst-inspect v4l2src

sys/v4l2/Makefile.am
sys/v4l2/gstv4l2element-marshal.list [new file with mode: 0644]
sys/v4l2/gstv4l2element.c
sys/v4l2/gstv4l2element.h
sys/v4l2/gstv4l2src.c
sys/v4l2/gstv4l2src.h
sys/v4l2/v4l2-overlay_calls.c
sys/v4l2/v4l2_calls.c
sys/v4l2/v4l2_calls.h
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index 976e730..84da9a9 100644 (file)
@@ -4,7 +4,7 @@ plugin_LTLIBRARIES = \
        libgstv4l2element.la \
        libgstv4l2src.la
 
-libgstv4l2element_la_SOURCES = gstv4l2element.c v4l2_calls.c v4l2-overlay_calls.c
+libgstv4l2element_la_SOURCES = gstv4l2element.c v4l2_calls.c v4l2-overlay_calls.c gstv4l2element-marshal.c
 libgstv4l2element_la_CFLAGS = $(GST_CFLAGS)
 libgstv4l2element_la_LIBADD =
 libgstv4l2element_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
@@ -15,4 +15,32 @@ libgstv4l2src_la_LIBADD = libgstv4l2element.la
 libgstv4l2src_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = gstv4l2element.h v4l2_calls.h \
-               gstv4l2src.h v4l2src_calls.h
+               gstv4l2src.h v4l2src_calls.h gstv4l2element-marshal.h
+
+EXTRA_libgstv4l2element_la_SOURCES = \
+       gstv4l2element-marshal.list
+
+BUILT_SOURCES = \
+       gstv4l2element-marshal.c \
+       gstv4l2element-marshal.h
+
+gstv4l2element-marshal.h: gstv4l2element-marshal.list
+       glib-genmarshal --header --prefix=gstv4l2_cclosure_marshal $(srcdir)/gstv4l2element-marshal.list > gstv4l2element-marshal.h.tmp
+       mv gstv4l2element-marshal.h.tmp gstv4l2element-marshal.h
+
+gstv4l2element-marshal.c: gstv4l2element-marshal.list
+       echo "#include \"glib.h\"" > gstv4l2element-marshal.c.tmp
+       echo "#include \"glib-object.h\"" >> gstv4l2element-marshal.c.tmp
+       echo "#include \"gstv4l2element-marshal.h\"" >> gstv4l2element-marshal.c.tmp
+       glib-genmarshal --body --prefix=gstv4l2_cclosure_marshal $(srcdir)/gstv4l2element-marshal.list >> gstv4l2element-marshal.c.tmp
+       mv gstv4l2element-marshal.c.tmp gstv4l2element-marshal.c
+
+# Don't want the generated marshal files in the dist
+dist-hook:
+       rm -f $(distdir)/gstv4l2element-marshal.c
+       rm -f $(distdir)/gstv4l2element-marshal.h
+
+# Clean generated files
+distclean-local:
+       rm -f $(top_builddir)/src/element/gstv4l2element-marshal.c
+       rm -f $(top_builddir)/src/element/gstv4l2element-marshal.h
diff --git a/sys/v4l2/gstv4l2element-marshal.list b/sys/v4l2/gstv4l2element-marshal.list
new file mode 100644 (file)
index 0000000..4321121
--- /dev/null
@@ -0,0 +1,3 @@
+BOOLEAN:INT,INT,INT,INT,POINTER,INT
+BOOLEAN:STRING,INT
+BOOLEAN:STRING,POINTER
index edff15b..926e4a5 100644 (file)
@@ -22,6 +22,7 @@
 #endif
 
 #include "v4l2_calls.h"
+#include "gstv4l2element-marshal.h"
 
 /* elementfactory details */
 static GstElementDetails gst_v4l2element_details = {
@@ -39,6 +40,9 @@ enum {
        /* FILL ME */
        SIGNAL_OPEN,
        SIGNAL_CLOSE,
+       SIGNAL_SET_VIDEOWINDOW,
+       SIGNAL_GET_ATTRIBUTE,
+       SIGNAL_SET_ATTRIBUTE,
        LAST_SIGNAL
 };
 
@@ -54,15 +58,13 @@ enum {
        ARG_FREQUENCY,
        ARG_SIGNAL_STRENGTH,
        ARG_HAS_AUDIO,
-       ARG_ATTRIBUTE,
-       ARG_ATTRIBUTE_SETS,
+       ARG_ATTRIBUTES,
        ARG_DEVICE,
        ARG_DEVICE_NAME,
        ARG_DEVICE_HAS_CAPTURE,
        ARG_DEVICE_HAS_OVERLAY,
        ARG_DEVICE_HAS_PLAYBACK,
        ARG_DISPLAY,
-       ARG_VIDEOWINDOW,
        ARG_DO_OVERLAY,
 };
 
@@ -153,11 +155,8 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass)
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_AUDIO,
                g_param_spec_boolean("has_audio","has_audio","has_audio",
                0,G_PARAM_READABLE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTE,
-               g_param_spec_pointer("attribute","attribute","attribute",
-               G_PARAM_READWRITE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTE_SETS,
-               g_param_spec_pointer("attribute_sets","attribute_sets","attribute_sets",
+       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTES,
+               g_param_spec_pointer("attributes","attributes","attributes",
                G_PARAM_READABLE));
 
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
@@ -183,9 +182,37 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass)
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DO_OVERLAY,
                g_param_spec_boolean("do_overlay","do_overlay","do_overlay",
                0,G_PARAM_WRITABLE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VIDEOWINDOW,
-               g_param_spec_pointer("videowindow","videowindow","videowindow",
-               G_PARAM_WRITABLE));
+
+       /* actions */
+       gst_v4l2element_signals[SIGNAL_SET_VIDEOWINDOW] =
+               g_signal_new ("set_videowindow",
+                       G_TYPE_FROM_CLASS(klass),
+                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                       G_STRUCT_OFFSET(GstV4l2ElementClass, set_videowindow),
+                       NULL, NULL,
+                       gstv4l2_cclosure_marshal_BOOLEAN__INT_INT_INT_INT_POINTER_INT,
+                       G_TYPE_BOOLEAN, 6,
+                       G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
+                       G_TYPE_POINTER, G_TYPE_INT);
+       klass->set_videowindow = gst_v4l2_set_window;
+       gst_v4l2element_signals[SIGNAL_GET_ATTRIBUTE] =
+               g_signal_new ("get_attribute",
+                       G_TYPE_FROM_CLASS(klass),
+                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                       G_STRUCT_OFFSET(GstV4l2ElementClass, get_attribute),
+                       NULL, NULL,
+                       gstv4l2_cclosure_marshal_BOOLEAN__STRING_POINTER,
+                       G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_POINTER);
+       klass->get_attribute = gst_v4l2_get_attribute;
+       gst_v4l2element_signals[SIGNAL_SET_ATTRIBUTE] =
+               g_signal_new ("set_attribute",
+                       G_TYPE_FROM_CLASS(klass),
+                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                       G_STRUCT_OFFSET(GstV4l2ElementClass, set_attribute),
+                       NULL, NULL,
+                       gstv4l2_cclosure_marshal_BOOLEAN__STRING_INT,
+                       G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_INT);
+       klass->set_attribute = gst_v4l2_set_attribute;
 
        /* signals */
        gst_v4l2element_signals[SIGNAL_OPEN] =
@@ -220,9 +247,14 @@ gst_v4l2element_init (GstV4l2Element *v4l2element)
        v4l2element->frequency = 0;
 
        v4l2element->controls = NULL;
+       v4l2element->menus = NULL;
+       v4l2element->control_specs = NULL;
        v4l2element->outputs = NULL;
+       v4l2element->output_names = NULL;
        v4l2element->inputs = NULL;
+       v4l2element->input_names = NULL;
        v4l2element->norms = NULL;
+       v4l2element->norm_names = NULL;
 }
 
 
@@ -267,13 +299,6 @@ gst_v4l2element_set_property (GObject      *object,
                                        return;
                        }
                        break;
-               case ARG_ATTRIBUTE:
-                       if (GST_V4L2_IS_OPEN(v4l2element)) {
-                               gst_v4l2_set_attribute(v4l2element,
-                                       ((GstV4l2Attribute*)g_value_get_pointer(value))->index,
-                                       ((GstV4l2Attribute*)g_value_get_pointer(value))->value);
-                       }
-                       break;
                case ARG_DEVICE:
                        if (!GST_V4L2_IS_OPEN(v4l2element)) {
                                if (v4l2element->device)
@@ -285,15 +310,6 @@ gst_v4l2element_set_property (GObject      *object,
                        if (!gst_v4l2_set_display(v4l2element, g_value_get_string(value)))
                                return;
                        break;
-               case ARG_VIDEOWINDOW:
-                       if (GST_V4L2_IS_OPEN(v4l2element)) {
-                               GByteArray *array = (GByteArray *) g_value_get_pointer(value);
-                               struct v4l2_clip *clips = (struct v4l2_clip *) array->data;
-                               gst_v4l2_set_window(v4l2element,
-                                       clips->c.left, clips->c.top, clips->c.width, clips->c.height,
-                                       &clips[1], array->len/sizeof(struct v4l2_clip)-1);
-                       }
-                       break;
                case ARG_DO_OVERLAY:
                        if (GST_V4L2_IS_OPEN(v4l2element)) {
                                if (!gst_v4l2_enable_overlay(v4l2element, g_value_get_boolean(value)))
@@ -316,7 +332,6 @@ gst_v4l2element_get_property (GObject    *object,
        GstV4l2Element *v4l2element;
        gint temp_i = 0;
        gulong temp_ul = 0;
-       GList *list = NULL;
 
        /* it's not null if we got it, but it might not be ours */
        g_return_if_fail(GST_IS_V4L2ELEMENT(object));
@@ -329,9 +344,7 @@ gst_v4l2element_get_property (GObject    *object,
                        g_value_set_int(value, temp_i);
                        break;
                case ARG_CHANNEL_NAMES:
-                       if (GST_V4L2_IS_OPEN(v4l2element))
-                               list = gst_v4l2_get_input_names(v4l2element);
-                       g_value_set_pointer(value, list);
+                       g_value_set_pointer(value, v4l2element->input_names);
                        break;
                case ARG_OUTPUT:
                        if (GST_V4L2_IS_OPEN(v4l2element))
@@ -339,9 +352,7 @@ gst_v4l2element_get_property (GObject    *object,
                        g_value_set_int(value, temp_i);
                        break;
                case ARG_OUTPUT_NAMES:
-                       if (GST_V4L2_IS_OPEN(v4l2element))
-                               list = gst_v4l2_get_output_names(v4l2element);
-                       g_value_set_pointer(value, list);
+                       g_value_set_pointer(value, v4l2element->output_names);
                        break;
                case ARG_NORM:
                        if (GST_V4L2_IS_OPEN(v4l2element))
@@ -349,9 +360,7 @@ gst_v4l2element_get_property (GObject    *object,
                        g_value_set_int(value, temp_i);
                        break;
                case ARG_NORM_NAMES:
-                       if (GST_V4L2_IS_OPEN(v4l2element))
-                               list = gst_v4l2_get_norm_names(v4l2element);
-                       g_value_set_pointer(value, list);
+                       g_value_set_pointer(value, v4l2element->norm_names);
                        break;
                case ARG_HAS_TUNER:
                        if (GST_V4L2_IS_OPEN(v4l2element))
@@ -373,23 +382,15 @@ gst_v4l2element_get_property (GObject    *object,
                                temp_i = gst_v4l2_has_audio(v4l2element);
                        g_value_set_boolean(value, temp_i>0?TRUE:FALSE);
                        break;
-               case ARG_ATTRIBUTE:
-                       if (GST_V4L2_IS_OPEN(v4l2element))
-                               gst_v4l2_get_attribute(v4l2element,
-                                       ((GstV4l2Attribute*)g_value_get_pointer(value))->index, &temp_i);
-                       ((GstV4l2Attribute*)g_value_get_pointer(value))->value = temp_i;
-                       break;
-               case ARG_ATTRIBUTE_SETS:
-                       if (GST_V4L2_IS_OPEN(v4l2element))
-                               list = gst_v4l2_get_attributes(v4l2element);
-                       g_value_set_pointer(value, list);
+               case ARG_ATTRIBUTES:
+                       g_value_set_pointer(value, v4l2element->control_specs);
                        break;
                case ARG_DEVICE:
-                       g_value_set_string(value, g_strdup(v4l2element->device));
+                       g_value_set_string(value, v4l2element->device);
                        break;
                case ARG_DEVICE_NAME:
                        if (GST_V4L2_IS_OPEN(v4l2element))
-                               g_value_set_string(value, g_strdup(v4l2element->vcap.card));
+                               g_value_set_string(value, v4l2element->vcap.card);
                        break;
                case ARG_DEVICE_HAS_CAPTURE:
                        if (GST_V4L2_IS_OPEN(v4l2element) &&
index 87ebaad..0e46203 100644 (file)
 typedef        struct _GstV4l2Element          GstV4l2Element;
 typedef        struct _GstV4l2ElementClass     GstV4l2ElementClass;
 
-typedef enum {
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_INTEGER = V4L2_CTRL_TYPE_INTEGER,
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_BOOLEAN = V4L2_CTRL_TYPE_BOOLEAN,
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_MENU    = V4L2_CTRL_TYPE_MENU,
-       GST_V4L2_ATTRIBUTE_VALUE_TYPE_BUTTON  = V4L2_CTRL_TYPE_BUTTON,
-} GstV4l2AttributeValueType;
-
-typedef enum {
-       GST_V4L2_ATTRIBUTE_TYPE_VIDEO,
-       GST_V4L2_ATTRIBUTE_TYPE_AUDIO,
-       GST_V4L2_ATTRIBUTE_TYPE_OTHER,
-} GstV4l2AttributeType;
-
-typedef struct _GstV4l2Attribute {
-       gint index;
-       gchar *name;
-       GstV4l2AttributeType type;
-       GstV4l2AttributeValueType val_type;
-       gint min, max, value;
-       GList *list_items; /* in case of 'list' */
-} GstV4l2Attribute;
-
 struct _GstV4l2Element {
        GstElement element;
 
@@ -79,10 +57,10 @@ struct _GstV4l2Element {
        struct v4l2_capability vcap;
 
        /* the toys available to us */
-       GList /*v4l2_input*/ *inputs;
-       GList /*v4l2_output*/ *outputs;
-       GList /*v4l2_enumstd*/ *norms;
-       GList /*v4l2_queryctrl*/ *controls;
+       GList /*v4l2_input*/ *inputs, *input_names;
+       GList /*v4l2_output*/ *outputs, *output_names;
+       GList /*v4l2_enumstd*/ *norms, *norm_names;
+       GList /*v4l2_queryctrl*/ *controls, *control_specs;
        GList /*GList:v4l2_querymenu*/ *menus;
 
        /* caching values */
@@ -96,10 +74,25 @@ struct _GstV4l2ElementClass {
        GstElementClass parent_class;
 
        /* signals */
-       void (*open)    (GstElement  *element,
-                        const gchar *device);
-       void (*close)   (GstElement  *element,
-                        const gchar *device);
+       void     (*open)            (GstElement  *element,
+                                    const gchar *device);
+       void     (*close)           (GstElement  *element,
+                                    const gchar *device);
+
+       /* actions */
+       gboolean (*set_videowindow) (GstElement  *element,
+                                    gint         x_offset,
+                                    gint         y_offset,
+                                    gint         height,
+                                    gint         width,
+                                    struct v4l2_clip *clips,
+                                    gint         num_clips);
+       gboolean (*get_attribute)   (GstElement  *element,
+                                    const gchar *attr_name,
+                                    int         *value);
+       gboolean (*set_attribute)   (GstElement  *element,
+                                    const gchar *attr_name,
+                                    const int    value);
 };
 
 
index c84993a..3dc6c9a 100644 (file)
@@ -45,8 +45,6 @@ enum {
        ARG_HEIGHT,
        ARG_PALETTE,
        ARG_PALETTE_NAMES,
-       ARG_FOURCC,
-       ARG_FOURCC_LIST,
        ARG_NUMBUFS,
        ARG_BUFSIZE
 };
@@ -154,12 +152,6 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass)
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PALETTE_NAMES,
                g_param_spec_pointer("palette_name","palette_name","palette_name",
                G_PARAM_READABLE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FOURCC,
-               g_param_spec_string("fourcc","fourcc","fourcc",
-               NULL,G_PARAM_READWRITE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FOURCC_LIST,
-               g_param_spec_pointer("fourcc_list","fourcc_list","fourcc_list",
-               G_PARAM_READABLE));
 
        g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NUMBUFS,
                g_param_spec_int("num_buffers","num_buffers","num_buffers",
@@ -201,6 +193,7 @@ gst_v4l2src_init (GstV4l2Src *v4l2src)
        v4l2src->breq.count = 0;
 
        v4l2src->formats = NULL;
+       v4l2src->format_list = NULL;
 }
 
 
@@ -742,19 +735,6 @@ gst_v4l2src_set_property (GObject      *object,
                        }
                        break;
 
-               case ARG_FOURCC:
-                       if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) {
-                               gint i;
-                               const gchar *formatstr = g_value_get_string(value);
-                               guint32 fourcc = GST_MAKE_FOURCC(formatstr[0],formatstr[1],formatstr[2],formatstr[3]);
-                               for (i=0;i<g_list_length(v4l2src->formats);i++) {
-                                       struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, i);
-                                       if (fmt->pixelformat == fourcc)
-                                               v4l2src->palette = i;
-                               }
-                       }
-                       break;
-
                case ARG_NUMBUFS:
                        if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) {
                                v4l2src->breq.count = g_value_get_int(value);
@@ -793,18 +773,7 @@ gst_v4l2src_get_property (GObject    *object,
                        break;
 
                case ARG_PALETTE_NAMES:
-                       g_value_set_pointer(value, gst_v4l2src_get_format_list(v4l2src));
-                       break;
-
-               case ARG_FOURCC: {
-                       struct v4l2_fmtdesc *fmt = g_list_nth_data(v4l2src->formats, v4l2src->palette);
-                       guint32 print_format = GUINT32_FROM_LE(fmt->pixelformat);
-                       gchar *print_format_str = (gchar *) &print_format;
-                       g_value_set_string(value, g_strndup(print_format_str, 4));
-                       break; }
-
-               case ARG_FOURCC_LIST:
-                       g_value_set_pointer(value, gst_v4l2src_get_fourcc_list(v4l2src));
+                       g_value_set_pointer(value, v4l2src->format_list);
                        break;
 
                case ARG_NUMBUFS:
index d287076..401161c 100644 (file)
@@ -45,7 +45,7 @@ struct _GstV4l2Src {
        GstPad *srcpad;
 
        /* internal lists */
-       GList /*v4l2_fmtdesc*/ *formats; /* list of available capture formats */
+       GList /*v4l2_fmtdesc*/ *formats, *format_list; /* list of available capture formats */
 
        /* buffer properties */
        struct v4l2_buffer bufsettings;
index ad3ec78..a78cdc6 100644 (file)
@@ -81,7 +81,7 @@ gst_v4l2_set_display (GstV4l2Element *v4l2element,
  ******************************************************/
 
 gboolean
-gst_v4l2_set_window (GstV4l2Element   *v4l2element,
+gst_v4l2_set_window (GstElement       *element,
                      gint              x,
                      gint              y,
                      gint              w,
@@ -90,6 +90,7 @@ gst_v4l2_set_window (GstV4l2Element   *v4l2element,
                      gint              num_clips)
 {
        struct v4l2_format fmt;
+       GstV4l2Element *v4l2element = GST_V4L2ELEMENT(element);
 
        DEBUG("trying to set video window to %dx%d,%d,%d", x,y,w,h);
        GST_V4L2_CHECK_OVERLAY(v4l2element);
index cb10841..24d2574 100644 (file)
@@ -90,6 +90,8 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
                inpptr = g_malloc(sizeof(input));
                memcpy(inpptr, &input, sizeof(input));
                v4l2element->inputs = g_list_append(v4l2element->inputs, inpptr);
+
+               v4l2element->input_names = g_list_append(v4l2element->input_names, inpptr->name);
        }
 
        /* outputs */
@@ -109,6 +111,8 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
                outptr = g_malloc(sizeof(output));
                memcpy(outptr, &output, sizeof(output));
                v4l2element->outputs = g_list_append(v4l2element->outputs, outptr);
+
+               v4l2element->output_names = g_list_append(v4l2element->output_names, outptr->name);
        }
 
        /* norms... */
@@ -128,12 +132,15 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
                stdptr = g_malloc(sizeof(standard));
                memcpy(stdptr, &standard, sizeof(standard));
                v4l2element->norms = g_list_append(v4l2element->norms, stdptr);
+
+               v4l2element->norm_names = g_list_append(v4l2element->norm_names, stdptr->name);
        }
 
        /* and lastly, controls+menus (if appropriate) */
        for (n=V4L2_CID_BASE;;n++) {
                struct v4l2_queryctrl control, *ctrlptr;
                GList *menus = NULL;
+               GParamSpec *spec = NULL;
                /* hacky... */
                if (n == V4L2_CID_LASTP1)
                        n = V4L2_CID_PRIVATE_BASE;
@@ -178,6 +185,30 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
                        }
                }
                v4l2element->menus = g_list_append(v4l2element->menus, menus);
+
+               switch (control.type) {
+                       case V4L2_CTRL_TYPE_INTEGER:
+                               spec = g_param_spec_int(ctrlptr->name, ctrlptr->name,
+                                                       ctrlptr->name, ctrlptr->minimum, ctrlptr->maximum,
+                                                       ctrlptr->default_value, G_PARAM_READWRITE);
+                               break;
+                       case V4L2_CTRL_TYPE_BOOLEAN:
+                               spec = g_param_spec_boolean(ctrlptr->name, ctrlptr->name,
+                                                       ctrlptr->name, ctrlptr->default_value,
+                                                       G_PARAM_READWRITE);
+                               break;
+                       case V4L2_CTRL_TYPE_MENU:
+                               /* hacky... we abuse pointer for 'no value' */
+                               spec = g_param_spec_pointer(ctrlptr->name, ctrlptr->name,
+                                                       ctrlptr->name, G_PARAM_WRITABLE);
+                               break;
+                       case V4L2_CTRL_TYPE_BUTTON:
+                               /* help?!? */
+                               spec = NULL;
+                               break;
+               }
+
+               v4l2element->control_specs = g_list_append(v4l2element->control_specs, spec);
        }
 
        return TRUE;
@@ -195,16 +226,22 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
                v4l2element->inputs = g_list_remove(v4l2element->inputs, data);
                g_free(data);
        }
+       g_list_free(v4l2element->input_names);
+       v4l2element->input_names = NULL;
        while (g_list_length(v4l2element->outputs) > 0) {
                gpointer data = g_list_nth_data(v4l2element->outputs, 0);
                v4l2element->outputs = g_list_remove(v4l2element->outputs, data);
                g_free(data);
        }
+       g_list_free(v4l2element->output_names);
+       v4l2element->output_names = NULL;
        while (g_list_length(v4l2element->norms) > 0) {
                gpointer data = g_list_nth_data(v4l2element->norms, 0);
                v4l2element->norms = g_list_remove(v4l2element->norms, data);
                g_free(data);
        }
+       g_list_free(v4l2element->norm_names);
+       v4l2element->norm_names = NULL;
        while (g_list_length(v4l2element->controls) > 0) {
                gpointer data = g_list_nth_data(v4l2element->controls, 0);
                v4l2element->controls = g_list_remove(v4l2element->controls, data);
@@ -220,6 +257,11 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
                        g_free(data);
                }
        }
+       while (g_list_length(v4l2element->control_specs) > 0) {
+               gpointer data = g_list_nth_data(v4l2element->control_specs, 0);
+               v4l2element->control_specs = g_list_remove(v4l2element->control_specs, data);
+               g_param_spec_unref(G_PARAM_SPEC(data));
+       }
 }
 
 
@@ -376,29 +418,6 @@ gst_v4l2_set_norm (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l2_get_norm_names()
- *   Get the list of available norms
- * return value: the list
- ******************************************************/
-
-GList *
-gst_v4l2_get_norm_names (GstV4l2Element *v4l2element)
-{
-       GList *names = NULL;
-       gint n;
-
-       DEBUG("getting a list of norm names");
-
-       for (n=0;n<g_list_length(v4l2element->norms);n++) {
-               struct v4l2_standard *standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
-               names = g_list_append(names, g_strdup(standard->name));
-       }
-
-       return names;
-}
-
-
-/******************************************************
  * gst_v4l2_get_input()
  *   Get the input of the current device
  * return value: TRUE on success, FALSE on error
@@ -459,29 +478,6 @@ gst_v4l2_set_input (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l2_get_input_names()
- *   Get the list of available input channels
- * return value: the list
- ******************************************************/
-
-GList *
-gst_v4l2_get_input_names (GstV4l2Element *v4l2element)
-{
-       GList *names = NULL;
-       gint n;
-
-       DEBUG("getting a list of input names");
-
-       for (n=0;n<g_list_length(v4l2element->inputs);n++) {
-               struct v4l2_input *input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, n);
-               names = g_list_append(names, g_strdup(input->name));
-       }
-
-       return names;
-}
-
-
-/******************************************************
  * gst_v4l2_get_output()
  *   Get the output of the current device
  * return value: TRUE on success, FALSE on error
@@ -542,30 +538,7 @@ gst_v4l2_set_output (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l2_get_output_names()
- *   Get the list of available output channels
- * return value: the list, or NULL on error
- ******************************************************/
-
-GList *
-gst_v4l2_get_output_names (GstV4l2Element *v4l2element)
-{
-       GList *names = NULL;
-       gint n;
-
-       DEBUG("getting a list of output names");
-
-       for (n=0;n<g_list_length(v4l2element->outputs);n++) {
-               struct v4l2_output *output = (struct v4l2_output *) g_list_nth_data(v4l2element->outputs, n);
-               names = g_list_append(names, g_strdup(output->name));
-       }
-
-       return names;
-}
-
-
-/******************************************************
- * gst_v4l_has_tuner():
+ * gst_v4l2_has_tuner():
  *   Check whether the device has a tuner
  * return value: TRUE if it has a tuner, else FALSE
  ******************************************************/
@@ -595,7 +568,7 @@ gst_v4l2_has_tuner (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l_get_frequency():
+ * gst_v4l2_get_frequency():
  *   get the current frequency
  * return value: TRUE on success, FALSE on error
  ******************************************************/
@@ -628,7 +601,7 @@ gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l_set_frequency():
+ * gst_v4l2_set_frequency():
  *   set frequency
  * return value: TRUE on success, FALSE on error
  ******************************************************/
@@ -661,7 +634,7 @@ gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l_signal_strength():
+ * gst_v4l2_signal_strength():
  *   get the strength of the signal on the current input
  * return value: TRUE on success, FALSE on error
  ******************************************************/
@@ -689,7 +662,7 @@ gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l_has_audio():
+ * gst_v4l2_has_audio():
  *   Check whether the device has audio capabilities
  * return value: TRUE if it has a tuner, else FALSE
  ******************************************************/
@@ -713,96 +686,53 @@ gst_v4l2_has_audio (GstV4l2Element *v4l2element)
 
 
 /******************************************************
- * gst_v4l_get_attributes():
- *   get a list of attributes available on this device
- * return value: the list
+ * gst_v4l2_control_name_to_num():
+ *   convert name to num (-1 if nothing)
  ******************************************************/
 
-GList *
-gst_v4l2_get_attributes        (GstV4l2Element *v4l2element)
+static gint
+gst_v4l2_control_name_to_num (GstV4l2Element *v4l2element,
+                              const gchar    *name)
 {
-       gint i;
-       GList *list = NULL;
-
-       DEBUG("getting a list of available attributes");
-
-       for (i=0;i<g_list_length(v4l2element->controls);i++) {
-               struct v4l2_queryctrl *control = (struct v4l2_queryctrl *) g_list_nth_data(v4l2element->controls, i);
-               GstV4l2Attribute* attribute = g_malloc(sizeof(GstV4l2Attribute));
-               attribute->name = g_strdup(control->name);
-               attribute->index = i;
-               attribute->list_items = NULL;
-               attribute->val_type = control->type;
-               if (control->type == V4L2_CTRL_TYPE_MENU) {
-                       /* list items */
-                       gint n;
-                       GList *menus = (GList *) g_list_nth_data(v4l2element->menus, i);
-                       for (n=0;n<g_list_length(menus);n++) {
-                               struct v4l2_querymenu *menu = g_list_nth_data(menus, n);
-                               attribute->list_items = g_list_append(attribute->list_items,
-                                                                       g_strdup(menu->name));
-                       }
-               }
-               switch (control->id) {
-                       case V4L2_CID_BRIGHTNESS:
-                       case V4L2_CID_CONTRAST:
-                       case V4L2_CID_SATURATION:
-                       case V4L2_CID_HUE:
-                       case V4L2_CID_BLACK_LEVEL:
-                       case V4L2_CID_AUTO_WHITE_BALANCE:
-                       case V4L2_CID_DO_WHITE_BALANCE:
-                       case V4L2_CID_RED_BALANCE:
-                       case V4L2_CID_BLUE_BALANCE:
-                       case V4L2_CID_GAMMA:
-                       case V4L2_CID_EXPOSURE:
-                       case V4L2_CID_AUTOGAIN:
-                       case V4L2_CID_GAIN:
-                       case V4L2_CID_HFLIP:
-                       case V4L2_CID_VFLIP:
-                       case V4L2_CID_HCENTER:
-                       case V4L2_CID_VCENTER:
-                               attribute->type = GST_V4L2_ATTRIBUTE_TYPE_VIDEO;
-                               break;
-                       case V4L2_CID_AUDIO_VOLUME:
-                       case V4L2_CID_AUDIO_BALANCE:
-                       case V4L2_CID_AUDIO_BASS:
-                       case V4L2_CID_AUDIO_TREBLE:
-                       case V4L2_CID_AUDIO_MUTE:
-                       case V4L2_CID_AUDIO_LOUDNESS:
-                               attribute->type = GST_V4L2_ATTRIBUTE_TYPE_AUDIO;
-                               break;
-                       default:
-                               attribute->type = GST_V4L2_ATTRIBUTE_TYPE_OTHER;
-                               break;
-               }
-               gst_v4l2_get_attribute(v4l2element, i, &attribute->value);
-               attribute->min = control->minimum;
-               attribute->max = control->maximum;
+       GList *item;
+
+       for (item = v4l2element->controls; item != NULL; item = item->next) {
+               struct v4l2_queryctrl *ctrl = item->data;
+               if (!strcmp(ctrl->name, name))
+                       return ctrl->id;
        }
 
-       return list;
+       return -1;
 }
 
 
 /******************************************************
- * gst_v4l_get_attribute():
+ * gst_v4l2_get_attribute():
  *   try to get the value of one specific attribute
  * return value: TRUE on success, FALSE on error
  ******************************************************/
 
 gboolean
-gst_v4l2_get_attribute (GstV4l2Element *v4l2element,
-                         gint            attribute_num,
-                         gint           *value)
+gst_v4l2_get_attribute (GstElement  *element,
+                         const gchar *name,
+                         int         *value)
 {
        struct v4l2_control control;
+       GstV4l2Element *v4l2element;
+       gint attribute_num = -1;
+
+       g_return_val_if_fail(element != NULL && name != NULL && value != NULL, FALSE);
+       g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE);
+       v4l2element = GST_V4L2ELEMENT(element);
 
        DEBUG("getting value of attribute %d", attribute_num);
        GST_V4L2_CHECK_OPEN(v4l2element);
 
-       if (attribute_num < 0 || attribute_num >= g_list_length(v4l2element->controls)) {
+       attribute_num = gst_v4l2_control_name_to_num(v4l2element, name);
+
+       if (attribute_num < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
-                       "Invalid control ID %d", attribute_num);
+                       "Invalid control %s", name);
                return FALSE;
        }
 
@@ -810,8 +740,8 @@ gst_v4l2_get_attribute      (GstV4l2Element *v4l2element,
 
        if (ioctl(v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
-                       "Failed to get value for control %d on device %s: %s",
-                       attribute_num, v4l2element->device, g_strerror(errno));
+                       "Failed to get value for control %s (%d) on device %s: %s",
+                       name, attribute_num, v4l2element->device, g_strerror(errno));
                return FALSE;
        }
 
@@ -822,24 +752,32 @@ gst_v4l2_get_attribute    (GstV4l2Element *v4l2element,
 
 
 /******************************************************
- * gst_v4l_set_attribute():
+ * gst_v4l2_set_attribute():
  *   try to set the value of one specific attribute
  * return value: TRUE on success, FALSE on error
  ******************************************************/
 
 gboolean
-gst_v4l2_set_attribute (GstV4l2Element *v4l2element,
-                         gint            attribute_num,
-                         gint            value)
+gst_v4l2_set_attribute (GstElement  *element,
+                         const gchar *name,
+                         const int    value)
 {
        struct v4l2_control control;
+       GstV4l2Element *v4l2element;
+       gint attribute_num = -1;
+
+       g_return_val_if_fail(element != NULL && name != NULL, FALSE);
+       g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE);
+       v4l2element = GST_V4L2ELEMENT(element);
 
        DEBUG("setting value of attribute %d to %d", attribute_num, value);
        GST_V4L2_CHECK_OPEN(v4l2element);
 
-       if (attribute_num < 0 || attribute_num >= g_list_length(v4l2element->controls)) {
+       attribute_num = gst_v4l2_control_name_to_num(v4l2element, name);
+
+       if (attribute_num < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
-                       "Invalid control ID %d", attribute_num);
+                       "Invalid control %s", name);
                return FALSE;
        }
 
@@ -848,8 +786,8 @@ gst_v4l2_set_attribute      (GstV4l2Element *v4l2element,
 
        if (ioctl(v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
                gst_element_error(GST_ELEMENT(v4l2element),
-                       "Failed to set value %d for control %d on device %s: %s",
-                       value, attribute_num, v4l2element->device, g_strerror(errno));
+                       "Failed to set value %d for control %s (%d) on device %s: %s",
+                       value, name, attribute_num, v4l2element->device, g_strerror(errno));
                return FALSE;
        }
 
index db9adc0..e03c7ab 100644 (file)
@@ -89,17 +89,14 @@ gboolean    gst_v4l2_get_norm               (GstV4l2Element *v4l2element,
                                                 gint           *norm);
 gboolean       gst_v4l2_set_norm               (GstV4l2Element *v4l2element,
                                                 gint            norm);
-GList *                gst_v4l2_get_norm_names         (GstV4l2Element *v4l2element);
 gboolean       gst_v4l2_get_input              (GstV4l2Element *v4l2element,
                                                 gint           *input);
 gboolean       gst_v4l2_set_input              (GstV4l2Element *v4l2element,
                                                 gint            input);
-GList *                gst_v4l2_get_input_names        (GstV4l2Element *v4l2element);
 gboolean       gst_v4l2_get_output             (GstV4l2Element *v4l2element,
                                                 gint           *output);
 gboolean       gst_v4l2_set_output             (GstV4l2Element *v4l2element,
                                                 gint            output);
-GList *                gst_v4l2_get_output_names       (GstV4l2Element *v4l2element);
 
 /* frequency control */
 gboolean       gst_v4l2_has_tuner              (GstV4l2Element *v4l2element,
@@ -113,18 +110,17 @@ gboolean  gst_v4l2_signal_strength        (GstV4l2Element *v4l2element,
 
 /* attribute control */
 gboolean       gst_v4l2_has_audio              (GstV4l2Element *v4l2element);
-GList *                gst_v4l2_get_attributes         (GstV4l2Element *v4l2element);
-gboolean       gst_v4l2_get_attribute          (GstV4l2Element *v4l2element,
-                                                gint            attribute_num,
-                                                gint           *value);
-gboolean       gst_v4l2_set_attribute          (GstV4l2Element *v4l2element,
-                                                gint            attribute_num,
-                                                gint            value);
+gboolean       gst_v4l2_get_attribute          (GstElement     *element,
+                                                const char     *attribute,
+                                                int            *value);
+gboolean       gst_v4l2_set_attribute          (GstElement     *element,
+                                                const char     *attribute,
+                                                const int       value);
 
 /* overlay */
 gboolean       gst_v4l2_set_display            (GstV4l2Element *v4l2element,
                                                 const gchar    *display);
-gboolean       gst_v4l2_set_window             (GstV4l2Element *v4l2element,
+gboolean       gst_v4l2_set_window             (GstElement     *element,
                                                 gint x,         gint y,
                                                 gint w,         gint h,
                                                 struct v4l2_clip *clips,
index a6f244f..d6c9655 100644 (file)
@@ -72,6 +72,8 @@ gst_v4l2src_fill_format_list (GstV4l2Src *v4l2src)
                fmtptr = g_malloc(sizeof(format));
                memcpy(fmtptr, &format, sizeof(format));
                v4l2src->formats = g_list_append(v4l2src->formats, fmtptr);
+
+               v4l2src->format_list = g_list_append(v4l2src->format_list, fmtptr->description);
        }
 
        return TRUE;
@@ -92,6 +94,8 @@ gst_v4l2src_empty_format_list (GstV4l2Src *v4l2src)
                v4l2src->formats = g_list_remove(v4l2src->formats, data);
                g_free(data);
        }
+       g_list_free(v4l2src->format_list);
+       v4l2src->format_list = NULL;
 
        return TRUE;
 }
@@ -399,49 +403,3 @@ gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src)
 
        return TRUE;
 }
-
-
-/******************************************************
- * gst_v4l2src_get_fourcc_list():
- *   create a list of all available fourccs
- * return value: the list
- ******************************************************/
-
-GList *
-gst_v4l2src_get_fourcc_list (GstV4l2Src *v4l2src)
-{
-       GList *list = NULL;
-       gint n;
-
-       for (n=0;n<g_list_length(v4l2src->formats);n++) {
-               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n);
-               guint32 print_format = GUINT32_FROM_LE(fmt->pixelformat);
-               gchar *print_format_str = (gchar *) &print_format;
-
-               list = g_list_append(list, g_strndup(print_format_str, 4));
-       }
-
-       return list;
-}
-
-
-/******************************************************
- * gst_v4l2src_get_format_list():
- *   create a list of all available capture formats
- * return value: the list
- ******************************************************/
-
-GList *
-gst_v4l2src_get_format_list (GstV4l2Src *v4l2src)
-{
-       GList *list = NULL;
-       gint n;
-
-       for (n=0;n<g_list_length(v4l2src->formats);n++) {
-               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, n);
-
-               list = g_list_append(list, g_strdup(fmt->description));
-       }
-
-       return list;
-}
index 436f65d..263d89a 100644 (file)
@@ -40,8 +40,6 @@ gboolean      gst_v4l2src_capture_deinit      (GstV4l2Src *v4l2src);
 
 gboolean       gst_v4l2src_fill_format_list    (GstV4l2Src *v4l2src);
 gboolean       gst_v4l2src_empty_format_list   (GstV4l2Src *v4l2src);
-GList *                gst_v4l2src_get_fourcc_list     (GstV4l2Src *v4l2src);
-GList *                gst_v4l2src_get_format_list     (GstV4l2Src *v4l2src);
 
 
 #endif /* __V4L2_SRC_CALLS_H__ */