Skip to content

Commit

Permalink
device: add generic feature read and write methods
Browse files Browse the repository at this point in the history
Dynamic language bindings can accept any type of a value so there is no
need to select correct method.
  • Loading branch information
kohtala authored and EmmanuelP committed Sep 4, 2024
1 parent 4e8f1b0 commit 7204118
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 4 deletions.
125 changes: 122 additions & 3 deletions src/arvdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,10 @@ arv_device_is_feature_implemented (ArvDevice *device, const char *feature, GErro
return ARV_IS_GC_FEATURE_NODE (node) && arv_gc_feature_node_is_implemented (ARV_GC_FEATURE_NODE (node), error);
}

static void *
static ArvGcNode *
_get_feature (ArvDevice *device, GType node_type, const char *feature, GError **error)
{
void *node;
ArvGcNode *node;

g_return_val_if_fail (ARV_IS_DEVICE (device), NULL);
g_return_val_if_fail (feature != NULL, NULL);
Expand Down Expand Up @@ -445,6 +445,126 @@ arv_device_execute_command (ArvDevice *device, const char *feature, GError **err
arv_gc_command_execute (ARV_GC_COMMAND (node), error);
}

/**
* arv_device_get_feature_value:
* @device: a #ArvDevice object
* @feature: feature name
* @value: (out): a uninitialized #GValue placeholder
* @error: a #GError placeholder
*
* Get the value of a feature. Enumeration values are returned as strings.
*
* Since: 0.8.32
*/

void
arv_device_get_feature_value (ArvDevice *device, const char *feature, GValue *value, GError **error)
{
ArvGcNode *node;
GError *local_error = NULL;

node = arv_device_get_feature (device, feature);

if (node == NULL) {
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_FEATURE_NOT_FOUND,
"[%s] Not found", feature);
return;
}

if (ARV_IS_GC_FLOAT (node)) {
g_value_init (value, G_TYPE_DOUBLE);
g_value_set_double (value, arv_gc_float_get_value (ARV_GC_FLOAT (node), &local_error));
} else if (ARV_IS_GC_ENUMERATION (node)) {
// ARV_IS_GC_INTEGER is true for an enum, so keep this before the int
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, arv_gc_enumeration_get_string_value (ARV_GC_ENUMERATION (node), &local_error));
} else if (ARV_IS_GC_INTEGER (node)) {
g_value_init (value, G_TYPE_INT64);
g_value_set_int64 (value, arv_gc_integer_get_value (ARV_GC_INTEGER (node), &local_error));
} else if (ARV_IS_GC_BOOLEAN (node)) {
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, arv_gc_boolean_get_value (ARV_GC_BOOLEAN (node), &local_error));
} else if (ARV_IS_GC_STRING (node)) {
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, arv_gc_string_get_value (ARV_GC_STRING (node), &local_error));
} else {
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not a feature", feature, G_OBJECT_TYPE_NAME (node));
}
}

/**
* arv_device_set_feature_value:
* @device: a #ArvDevice object
* @feature: feature name
* @value: a #GValue
* @error: a #GError placeholder
*
* Set value of a feature.
*
* Since: 0.8.32
*/

void
arv_device_set_feature_value (ArvDevice *device, const char *feature, const GValue *value, GError **error)
{
ArvGcNode *node;
GValue value_copy = G_VALUE_INIT;
GError *local_error = NULL;

node = arv_device_get_feature (device, feature);

if (node == NULL) {
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_FEATURE_NOT_FOUND,
"[%s] Not found", feature);
return;
}

if (ARV_IS_GC_FLOAT (node)) {
g_value_init(&value_copy, G_TYPE_DOUBLE);
if (g_value_transform(value, &value_copy))
arv_gc_float_set_value (ARV_GC_FLOAT (node), g_value_get_double (&value_copy), &local_error);
else
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not a double", feature, G_OBJECT_TYPE_NAME (node));
} else if (ARV_IS_GC_INTEGER (node)) {
g_value_init(&value_copy, G_TYPE_INT64);
if (g_value_transform(value, &value_copy))
arv_gc_integer_set_value (ARV_GC_INTEGER (node), g_value_get_int64 (&value_copy), &local_error);
else
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not an int64", feature, G_OBJECT_TYPE_NAME (node));
} else if (ARV_IS_GC_BOOLEAN (node)) {
g_value_init(&value_copy, G_TYPE_BOOLEAN);
if (g_value_transform(value, &value_copy))
arv_gc_boolean_set_value (ARV_GC_BOOLEAN (node), g_value_get_boolean (&value_copy), &local_error);
else
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not a boolean", feature, G_OBJECT_TYPE_NAME (node));
} else if (ARV_IS_GC_STRING (node)) {
g_value_init(&value_copy, G_TYPE_STRING);
if (g_value_transform(value, &value_copy))
arv_gc_string_set_value (ARV_GC_STRING (node), g_value_get_string (&value_copy), &local_error);
else
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not a string", feature, G_OBJECT_TYPE_NAME (node));
} else if (ARV_IS_GC_ENUMERATION (node)) {
if (G_VALUE_HOLDS_STRING (value))
arv_gc_enumeration_set_string_value (ARV_GC_ENUMERATION (node), g_value_get_string (value), &local_error);
else {
g_value_init(&value_copy, G_TYPE_INT64);
if (g_value_transform(value, &value_copy))
arv_gc_enumeration_set_int_value (ARV_GC_ENUMERATION (node), g_value_get_int64 (&value_copy), &local_error);
else
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not a string or int64", feature, G_OBJECT_TYPE_NAME (node));
}
} else {
g_set_error (error, ARV_DEVICE_ERROR, ARV_DEVICE_ERROR_WRONG_FEATURE,
"[%s:%s] Not a feature", feature, G_OBJECT_TYPE_NAME (node));
}
}

/**
* arv_device_set_boolean_feature_value:
* @device: a #ArvDevice
Expand Down Expand Up @@ -1278,4 +1398,3 @@ arv_device_initable_iface_init (GInitableIface *iface)
{
iface->init = arv_device_initable_init;
}

3 changes: 3 additions & 0 deletions src/arvdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ ARV_API ArvChunkParser *arv_device_create_chunk_parser (ArvDevice *device);

ARV_API void arv_device_execute_command (ArvDevice *device, const char *feature, GError **error);

ARV_API void arv_device_get_feature_value (ArvDevice *device, const char *feature, GValue *value, GError **error);
ARV_API void arv_device_set_feature_value (ArvDevice *device, const char *feature, const GValue *value, GError **error);

ARV_API void arv_device_set_boolean_feature_value (ArvDevice *device, const char *feature, gboolean value, GError **error);
ARV_API gboolean arv_device_get_boolean_feature_value (ArvDevice *device, const char *feature, GError **error);
ARV_API void arv_device_get_boolean_feature_value_gi (ArvDevice *device, const char *feature, gboolean *value, GError **error);
Expand Down
26 changes: 25 additions & 1 deletion tests/python/arv-feature-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@

from gi.repository import Aravis

Aravis.enable_interface("Fake")
try:
camera = Aravis.Camera.new (None)
camera = Aravis.Camera(name="Fake_1")
except TypeError:
print ("No camera found")
exit ()
Expand All @@ -27,3 +28,26 @@

print ("Width = %d" %(device.get_integer_feature_value ("Width")))
print ("Height = %d" %(device.get_integer_feature_value ("Height")))


def pt(x):
print(type(x), x)

pt(device.get_feature_value("DeviceVersion"))
device.set_feature_value("Width", 640.0)
pt(device.get_feature_value("Width"))
device.set_feature_value("AcquisitionFrameRate", 2)
pt(device.get_feature_value("AcquisitionFrameRate"))
device.set_feature_value("TestBoolean", True)
pt(device.get_feature_value("TestBoolean"))
try:
device.set_feature_value("TestBoolean", None)
except TypeError:
pass
else:
print("Expected TypeError")
device.set_feature_value("TestBoolean", 0)
pt(device.get_feature_value("TestBoolean"))
device.set_feature_value("TestStringReg", "TestValue")
pt(device.get_feature_value("TestStringReg"))
pt(device.get_feature_value("GainAuto"))

0 comments on commit 7204118

Please sign in to comment.