diff --git a/sys/gstniimaq.c b/sys/gstniimaq.c index c76e14b..5aea467 100644 --- a/sys/gstniimaq.c +++ b/sys/gstniimaq.c @@ -36,8 +36,10 @@ #include "config.h" #endif +#include "gst/interfaces/propertyprobe.h" + #include "gstniimaq.h" -//#include + #include #include @@ -53,15 +55,20 @@ GST_ELEMENT_DETAILS ("NI-IMAQ Video Source", enum { PROP_0, + PROP_INTERFACE, PROP_TIMESTAMP_OFFSET, PROP_BUFSIZE /* FILL ME */ }; +#define DEFAULT_PROP_INTERFACE "img0::0" #define DEFAULT_PROP_TIMESTAMP_OFFSET 0 #define DEFAULT_PROP_BUFSIZE 10 -GST_BOILERPLATE (GstNiImaq, gst_niimaq, GstPushSrc, GST_TYPE_PUSH_SRC); +static void gst_niimaq_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstNiImaq, gst_niimaq, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_niimaq_init_interfaces); /* GObject virtual methods */ static void gst_niimaq_dispose (GObject * object); @@ -97,6 +104,248 @@ static GstCaps *gst_niimaq_get_cam_caps (GstNiImaq * src); static void _____BEGIN_FUNCTIONS_____(); +/** +* gst_niimaq_probe_get_properties: +* @probe: #GstPropertyProbe +* +* Gets list of properties that can be probed +* +* Returns: #GList of properties that can be probed +*/ +static const GList * +gst_niimaq_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, "interface")); + } + + return list; +} + +static gboolean init = FALSE; +static GList *interfaces = NULL; + +/** +* gst_niimaq_class_probe_interfaces: +* @klass: #GstNiImaqClass +* @check: whether to enumerate interfaces +* +* Probes NI-IMAQ driver for available interfaces +* +* Returns: TRUE always +*/ +static gboolean +gst_niimaq_class_probe_interfaces (GstNiImaqClass * klass, gboolean check) +{ + if (!check) { + guint32 n; + gchar name[256]; + + /* clear interface list */ + while (interfaces) { + gchar *iface = interfaces->data; + interfaces = g_list_remove (interfaces, iface); + g_free (iface); + } + + /* enumerate interfaces, limiting ourselves to the first 64 */ + for (n = 0; n < 64; n++) { + guint32 iid; + guint32 nports; + guint32 port; + gchar * iname; + + /* get interface names until there are no more */ + if (imgInterfaceQueryNames (n, name) != 0) + break; + + /* ignore NICFGen */ + if (g_strcmp0 (name, "NICFGen.iid") == 0) + continue; + + /* try and open the interface */ + if (imgInterfaceOpen (name, &iid) != 0) + continue; + + /* find how many ports the interface provides */ + imgGetAttribute (iid, IMG_ATTR_NUM_PORTS, &nports); + imgClose (iid, TRUE); + + /* iterate over all the available ports */ + for (port=0; port < nports; port++) { + /* if the there are multiple ports append the port number */ + if (nports > 1) + iname = g_strdup_printf ("%s::%d", name, port); + else + iname = g_strdup (name); + + /* TODO: should check to see if a camera is actually attached */ + interfaces = g_list_append (interfaces, iname); + } + } + + init = TRUE; + } + + klass->interfaces = interfaces; + + return init; +} + +/** +* gst_niimaq_probe_probe_property: +* @probe: #GstPropertyProbe +* @prop_id: Property id +* @pspec: #GParamSpec +* +* GstPropertyProbe _probe_proprty vmethod implementation that probes a +* property for possible values +*/ +static void +gst_niimaq_probe_probe_property (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstNiImaqClass *klass = GST_NIIMAQ_GET_CLASS (probe); + + switch (prop_id) { + case PROP_INTERFACE: + gst_niimaq_class_probe_interfaces (klass, FALSE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } +} + +/** +* gst_niimaq_probe_needs_probe: +* @probe: #GstPropertyProbe +* @prop_id: Property id +* @pspec: #GParamSpec +* +* GstPropertyProbe _needs_probe vmethod implementation that indicates if +* a property needs to be updated +* +* Returns: TRUE if a property needs to be updated +*/ +static gboolean +gst_niimaq_probe_needs_probe (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstNiImaqClass *klass = GST_NIIMAQ_GET_CLASS (probe); + gboolean ret = FALSE; + + switch (prop_id) { + case PROP_INTERFACE: + ret = !gst_niimaq_class_probe_interfaces (klass, TRUE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return ret; +} + +/** +* gst_niimaq_class_list_interfaces: +* @klass: #GstNiImaqClass +* +* Returns: #GValueArray of interface names +*/ +static GValueArray * +gst_niimaq_class_list_interfaces (GstNiImaqClass * klass) +{ + GValueArray *array; + GValue value = { 0 }; + GList *item; + + if (!klass->interfaces) + return NULL; + + array = g_value_array_new (g_list_length (klass->interfaces)); + item = klass->interfaces; + g_value_init (&value, G_TYPE_STRING); + while (item) { + gchar *iface = item->data; + + g_value_set_string (&value, iface); + g_value_array_append (array, &value); + + item = item->next; + } + g_value_unset (&value); + + return array; +} + +/** +* gst_niimaq_probe_get_values: +* @probe: #GstPropertyProbe +* @prop_id: Property id +* @pspec: #GParamSpec +* +* GstPropertyProbe _get_values vmethod implementation that gets possible +* values for a property +* +* Returns: #GValueArray containing possible values for requested property +*/ +static GValueArray * +gst_niimaq_probe_get_values (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstNiImaqClass *klass = GST_NIIMAQ_GET_CLASS (probe); + GValueArray *array = NULL; + + switch (prop_id) { + case PROP_INTERFACE: + array = gst_niimaq_class_list_interfaces (klass); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return array; +} + +/** +* gst_v4l_property_probe_interface_init: +* @iface: #GstPropertyProbeInterface +* +* Install property probe interfaces functions +*/ +static void +gst_niimaq_property_probe_interface_init (GstPropertyProbeInterface * iface) +{ + iface->get_properties = gst_niimaq_probe_get_properties; + iface->probe_property = gst_niimaq_probe_probe_property; + iface->needs_probe = gst_niimaq_probe_needs_probe; + iface->get_values = gst_niimaq_probe_get_values; +} + +/** +* gst_niimaq_init_interfaces: +* @type: #GType +* +* Initialize all interfaces +*/ +static void +gst_niimaq_init_interfaces (GType type) +{ + static const GInterfaceInfo niimaq_propertyprobe_info = { + (GInterfaceInitFunc) gst_niimaq_property_probe_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, + GST_TYPE_PROPERTY_PROBE, &niimaq_propertyprobe_info); +} + static void gst_niimaq_base_init (gpointer g_class) { @@ -127,6 +376,11 @@ gst_niimaq_class_init (GstNiImaqClass * klass) gobject_class->set_property = gst_niimaq_set_property; gobject_class->get_property = gst_niimaq_get_property; + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_INTERFACE, g_param_spec_string ("interface", + "Interface", + "NI-IMAQ interface to open", DEFAULT_PROP_INTERFACE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", "Timestamp offset", @@ -165,7 +419,8 @@ gst_niimaq_init (GstNiImaq * src, GstNiImaqClass * g_class) src->buflist = 0; src->sid = 0; src->iid = 0; - src->device_name = g_strdup_printf ("img2"); + src->camera_name = g_strdup (DEFAULT_PROP_INTERFACE); + src->interface_name = g_strdup (DEFAULT_PROP_INTERFACE); } @@ -174,8 +429,11 @@ gst_niimaq_dispose (GObject * object) { GstNiImaq *src = GST_NIIMAQ (object); - g_free (src->device_name); - src->device_name = NULL; + g_free (src->camera_name); + src->camera_name = NULL; + + g_free (src->interface_name); + src->interface_name = NULL; G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -187,6 +445,15 @@ gst_niimaq_set_property (GObject * object, guint prop_id, GstNiImaq *src = GST_NIIMAQ (object); switch (prop_id) { + case PROP_INTERFACE: + if (src->interface_name) + g_free (src->interface_name); + src->interface_name = g_strdup (g_value_get_string (value)); + + if (src->camera_name) + g_free (src->camera_name); + src->camera_name = g_strdup (g_value_get_string (value)); + break; case PROP_TIMESTAMP_OFFSET: src->timestamp_offset = g_value_get_int64 (value); break; @@ -204,6 +471,9 @@ gst_niimaq_get_property (GObject * object, guint prop_id, GValue * value, GstNiImaq *src = GST_NIIMAQ (object); switch (prop_id) { + case PROP_INTERFACE: + g_value_set_string (value, src->interface_name); + break; case PROP_TIMESTAMP_OFFSET: g_value_set_int64 (value, src->timestamp_offset); break; @@ -514,12 +784,12 @@ gst_niimaq_start (GstBaseSrc * src) Int32 rval; int i; - GST_LOG_OBJECT (filter, "Opening camera interface: %s", filter->device_name); + GST_LOG_OBJECT (filter, "Opening camera interface: %s", filter->interface_name); filter->iid = 0; filter->sid = 0; - rval=imgInterfaceOpen(filter->device_name,&(filter->iid)); + rval=imgInterfaceOpen(filter->interface_name,&(filter->iid)); if (rval) { GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, ("Failed to open camera interface"), @@ -527,7 +797,7 @@ gst_niimaq_start (GstBaseSrc * src) goto error; } - GST_LOG_OBJECT (filter, "Opening camera session: %s", filter->device_name); + GST_LOG_OBJECT (filter, "Opening camera session: %s", filter->interface_name); rval=imgSessionOpen(filter->iid, &(filter->sid)); if (rval) { @@ -634,27 +904,3 @@ GST_VERSION_MINOR, "niimaq", "NI-IMAQ Video Source", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) - - - -// Enumerate cams -// rval=imgInterfaceQueryNames(idx, name); -//if(rval) -//break; -// -//rval=imgInterfaceOpen(name, &iid); -//if(rval) -//continue; -// -//imgGetAttribute(iid, IMG_ATTR_NUM_PORTS, &nPorts); -//imgClose(iid, TRUE); -//for(j=0;j1) { -// char num[33]; -// itoa(j,num,10); -// strcat(name,"::"); //FIXME: this is probably not safe -// strcat(name,num); //FIXME: this is probably not safe -// } -// rval=imgInterfaceOpen(name, &iid); -// if(rval) -// continue; diff --git a/sys/gstniimaq.h b/sys/gstniimaq.h index 65cb1a0..b61e91f 100644 --- a/sys/gstniimaq.h +++ b/sys/gstniimaq.h @@ -33,11 +33,13 @@ G_BEGIN_DECLS #define GST_NIIMAQ(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NIIMAQ,GstNiImaq)) #define GST_NIIMAQ_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NIIMAQ,GstNiImaq)) + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NIIMAQ,GstNiImaqClass)) #define GST_IS_NIIMAQ(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NIIMAQ)) #define GST_IS_NIIMAQ_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NIIMAQ)) +#define GST_NIIMAQ_GET_CLASS(klass) \ + (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_NIIMAQ, GstNiImaqClass)) typedef struct _GstNiImaq GstNiImaq; typedef struct _GstNiImaqClass GstNiImaqClass; @@ -65,7 +67,8 @@ struct _GstNiImaq { gint bufsize; guint32** buflist; - gchar *device_name; + gchar *camera_name; + gchar *interface_name; INTERFACE_ID iid; SESSION_ID sid; @@ -74,6 +77,9 @@ struct _GstNiImaq { struct _GstNiImaqClass { GstPushSrcClass parent_class; + + /* probed interfaces */ + GList *interfaces; }; GType gst_niimaq_get_type (void);