diff options
author | Timo Dritschler <timo.dritschler@kit.edu> | 2015-07-09 19:24:02 +0200 |
---|---|---|
committer | Timo Dritschler <timo.dritschler@kit.edu> | 2015-07-09 19:24:02 +0200 |
commit | f888aff829e9892d0b4655af6bc0ee3f9658bbb2 (patch) | |
tree | 31d9deefd2c02e766f6441e8f43481f0faa3d42d | |
parent | 1f04383dca16af05697812e634b1e34811f045a6 (diff) | |
download | uca-kiro-f888aff829e9892d0b4655af6bc0ee3f9658bbb2.tar.gz uca-kiro-f888aff829e9892d0b4655af6bc0ee3f9658bbb2.tar.bz2 uca-kiro-f888aff829e9892d0b4655af6bc0ee3f9658bbb2.tar.xz uca-kiro-f888aff829e9892d0b4655af6bc0ee3f9658bbb2.zip |
Some stuff.
Mostly build-fixes.
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rw-r--r-- | bin/kiro-camera-server.c | 20 | ||||
-rw-r--r-- | src/CMakeLists.txt | 12 | ||||
-rw-r--r-- | src/uca-kiro-camera.cpp | 1115 | ||||
-rw-r--r-- | src/uca-kiro-camera.h | 332 |
5 files changed, 340 insertions, 1146 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index fd0e914..4aeb72c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,14 +3,14 @@ project(KIROCS C) set(CMAKE_INCLUDE_CURRENT_DIR TRUE) -set(TARNAME "kiro-camera-server") +set(TARNAME "uca-kiro") set(LIBKIROCS_VERSION_MAJOR "0") set(LIBKIROCS_VERSION_MINOR "0") set(LIBKIROCS_VERSION_PATCH "1") set(LIBKIROCS_VERSION_RELEASE "0") set(LIBKIROCS_VERSION_STRING "${LIBKIROCS_VERSION_MAJOR}.${LIBKIROCS_VERSION_MINOR}.${LIBKIROCS_VERSION_PATCH}") set(VERSION "${LIBKIROCS_VERSION_STRING}") -set(LIBKIROCS_DESCRIPTION "Small InfiniBand communication Server and Client") +set(LIBKIROCS_DESCRIPTION "KIRO InfiniBand camera remote control server and plugin for libuca") # Increase the ABI version when binary compatibility cannot be guaranteed, e.g. # symbols have been removed, function signatures, structures, constants etc. @@ -31,6 +31,8 @@ pkg_check_modules(GIO2 gio-2.0>=2.32 REQUIRED) pkg_check_modules(LIBUCA libuca>=2.0 REQUIRED) pkg_check_modules(KIRO kiro>=1.4 REQUIRED) +pkg_check_variable(libuca plugindir) + include_directories( SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/src @@ -62,3 +64,4 @@ set(LIBKIROCS_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) add_definitions(-Wall -Wextra -std=c99) add_subdirectory(bin) +add_subdirectory(src) diff --git a/bin/kiro-camera-server.c b/bin/kiro-camera-server.c index cb14332..80683ac 100644 --- a/bin/kiro-camera-server.c +++ b/bin/kiro-camera-server.c @@ -19,7 +19,7 @@ #include <stdlib.h> #include <string.h> -#include "kiro-camera-server.h" +#include "uca-kiro-camera.h" #include "uca/uca-plugin-manager.h" @@ -124,20 +124,6 @@ gtype_size (GType type) } -gint -property_id_from_name(const gchar* name) -{ - gint idx = 0; - gboolean found = FALSE; - for (;idx < N_BASE_PROPERTIES; ++idx) { - if (0 == g_strcmp0(name, uca_camera_props[idx])) { - found = TRUE; - break; - } - } - return found ? idx : -1; -} - static void print_cam_name (gchar *name, gpointer unused) { @@ -222,7 +208,6 @@ connect_callback (gulong rank, gulong *storage) static KiroContinueFlag receive_callback (KiroMessageStatus *status, KiroCsData *data) { - PropUpdate *update = (PropUpdate *)status->message->payload; if (status->message->msg == KIROCS_EXIT) { g_message ("Peer requested shut down..."); @@ -230,6 +215,8 @@ receive_callback (KiroMessageStatus *status, KiroCsData *data) } if (status->message->msg == KIROCS_UPDATE) { + PropUpdate *update = (PropUpdate *)status->message->payload; + g_debug ("Unpacking ID %u\n", update->id); gpointer unpacked = unpack_scalar (update); @@ -240,6 +227,7 @@ receive_callback (KiroMessageStatus *status, KiroCsData *data) data->properties[update->id -1]->value_type, data->signal_handlers[update->id], unpacked); + g_free (unpacked); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe330b6..ed14dcc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,13 +1,13 @@ -include_directories(${KIROCS_SOURCE_DIR}) +include_directories(${KIROCS_INCLUDE_DIR} ${KIROCS_SOURCE_DIR}) link_directories(${KIROCS_BINARY_DIR}) -add_library(libucakiro SHARED uca-kiro-camera.c) -target_link_libraries(libucakiro ${KIROCS_DEPS}) +add_library(ucakiro SHARED uca-kiro-camera.c) +target_link_libraries(ucakiro ${KIROCS_DEPS}) -set_target_properties(libucakiro PROPERTIES +set_target_properties(ucakiro PROPERTIES VERSION "${LIBKIROCS_VERSION_MAJOR}.${LIBKIROCS_VERSION_MINOR}" SOVERSION ${LIBKIROCS_VERSION_PATCH} ) -install(FILES uca-kiro-camera.h DESTINATION ${KIROCS_BINDIR}) -install(TARGETS uca-kiro-camera LIBRARY DESTINATION ${LIBUCA_LIBDIR}/uca) +install(TARGETS ucakiro LIBRARY DESTINATION ${LIBUCA_PLUGINDIR}) +install(FILES uca-kiro-camera.h DESTINATION ${KIROCS_INCLUDEDIR}) diff --git a/src/uca-kiro-camera.cpp b/src/uca-kiro-camera.cpp deleted file mode 100644 index 4346a9f..0000000 --- a/src/uca-kiro-camera.cpp +++ /dev/null @@ -1,1115 +0,0 @@ -/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> - (Karlsruhe Institute of Technology) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2.1 of the License, or (at your - option) any later version. - - This library is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - details. - - You should have received a copy of the GNU Lesser General Public License along - with this library; if not, write to the Free Software Foundation, Inc., 51 - Franklin St, Fifth Floor, Boston, MA 02110, USA */ - - -#include <tango.h> - -extern "C" { -#include <gmodule.h> -#include <gio/gio.h> -#include <string.h> -#include <math.h> -#include <kiro/kiro-sb.h> -#include "uca-kiro-camera.h" -} // EXTERN C - -#define UCA_KIRO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UCA_TYPE_KIRO_CAMERA, UcaKiroCameraPrivate)) - -static void uca_kiro_initable_iface_init (GInitableIface *iface); -GError *initable_iface_error = NULL; - -G_DEFINE_TYPE_WITH_CODE (UcaKiroCamera, uca_kiro_camera, UCA_TYPE_CAMERA, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - uca_kiro_initable_iface_init)) - - -/** - * UcaCameraError: - @UCA_KIRO_CAMERA_ERROR_MISSING_TANGO_ADDRESS: No TANGO address ('kiro-tango-address') property was supplied during camera creation - @UCA_KIRO_CAMERA_ERROR_TANGO_CONNECTION_FAILED: Could not connect to the given TANGO address - @UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED: Failed to establish a KIRO connection to the given TANGO server - @UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED: A TANGO exception was raised during communication with the server - @UCA_KIRO_CAMERA_ERROR_BAD_CAMERA_INTERFACE: The given TANGO server does not expose the expected UcaCamera base interface - */ -GQuark uca_kiro_camera_error_quark() -{ - return g_quark_from_static_string ("uca-kiro-camera-error-quark"); -} - - -enum { - PROP_KIRO_ADDRESS = N_BASE_PROPERTIES, - PROP_KIRO_PORT, - PROP_KIRO_TANGO_ADDRESS, - PROP_KIRO_REMOTE_NAME, - N_PROPERTIES -}; - -static const gint kiro_overrideables[] = { - PROP_NAME, - 0, -}; - -static GParamSpec *kiro_properties[N_PROPERTIES] = { NULL, }; - -struct _UcaKiroCameraPrivate { - guint8 *dummy_data; - guint current_frame; - gchar *kiro_address; - gchar *kiro_port; - guint kiro_port_uint; - gchar *kiro_tango_address; - gchar *remote_name; - Tango::DeviceProxy *tango_device; - GParamSpec **kiro_dynamic_attributes; - - gboolean thread_running; - gboolean kiro_connected; - gboolean construction_error; - - GThread *grab_thread; - KiroSb *receive_buffer; - - guint roi_height; - guint roi_width; - guint bytes_per_pixel; -}; - -static gpointer -kiro_grab_func(gpointer data) -{ - UcaKiroCamera *kiro_camera = UCA_KIRO_CAMERA (data); - g_return_val_if_fail (UCA_IS_KIRO_CAMERA (kiro_camera), NULL); - - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (kiro_camera); - UcaCamera *camera = UCA_CAMERA (kiro_camera); - gdouble fps; - g_object_get (G_OBJECT (data), "frames-per-second", &fps, NULL); - const gulong sleep_time = (gulong) G_USEC_PER_SEC / fps; - - while (priv->thread_running) { - camera->grab_func (NULL, camera->user_data); - g_usleep (sleep_time); - } - - return NULL; -} - -static void -uca_kiro_camera_start_recording(UcaCamera *camera, GError **error) -{ - gboolean transfer_async = FALSE; - UcaKiroCameraPrivate *priv; - g_return_if_fail(UCA_IS_KIRO_CAMERA (camera)); - - priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); - g_object_get (G_OBJECT(camera), - "transfer-asynchronously", &transfer_async, - NULL); - - //'Cache' ROI settings from TANGO World - g_object_get (G_OBJECT(camera), - "roi-width", &priv->roi_width, - NULL); - g_object_get (G_OBJECT(camera), - "roi-height", &priv->roi_height, - NULL); - - size_t bits = 0; - g_object_get (G_OBJECT(camera), - "sensor-bitdepth", &bits, - NULL); - - priv->bytes_per_pixel = 1; - if (bits > 8) priv->bytes_per_pixel++; - if (bits > 16) priv->bytes_per_pixel++; - if (bits > 24) priv->bytes_per_pixel++; - - Tango::DevState state; - g_object_get (G_OBJECT(camera), - "State", &state, - NULL); - try { - if (Tango::DevState::STANDBY == state) - priv->tango_device->command_inout ("StartRecording"); - } - catch (Tango::DevFailed &e) { - g_warning ("Failed to execute 'StartRecording' on the remote camera due to a TANGO exception.\n"); - g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, - "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc); - return; - } - - - /* - * In case asynchronous transfer is requested, we start a new thread that - * invokes the grab callback, otherwise nothing will be done here. - */ - if (transfer_async) { - GError *tmp_error = NULL; - priv->thread_running = TRUE; - priv->grab_thread = g_thread_create (kiro_grab_func, camera, TRUE, &tmp_error); - - if (tmp_error != NULL) { - priv->thread_running = FALSE; - g_propagate_error (error, tmp_error); - try { - priv->tango_device->command_inout ("StopRecording"); - } - catch (Tango::DevFailed &e) { - g_warning ("Failed to execute 'StopRecording' on the remote camera due to a TANGO exception: '%s'\n", (const char *)e.errors[0].desc); - } - } - } - - kiro_sb_thaw (priv->receive_buffer); -} - -static void -uca_kiro_camera_stop_recording(UcaCamera *camera, GError **error) -{ - g_return_if_fail(UCA_IS_KIRO_CAMERA (camera)); - UcaKiroCameraPrivate *priv; - priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); - - Tango::DevState state; - g_object_get (G_OBJECT(camera), - "State", &state, - NULL); - - try { - if (Tango::DevState::RUNNING == state) - priv->tango_device->command_inout ("StopRecording"); - } - catch (Tango::DevFailed &e) { - g_warning ("Failed to execute 'StopRecording' on the remote camera due to a TANGO exception.\n"); - g_set_error (error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, - "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc); - } - - gboolean transfer_async = FALSE; - g_object_get(G_OBJECT (camera), - "transfer-asynchronously", &transfer_async, - NULL); - - if (transfer_async) { - priv->thread_running = FALSE; - g_thread_join (priv->grab_thread); - } - - kiro_sb_freeze (priv->receive_buffer); - g_free (priv->dummy_data); -} - -static void -uca_kiro_camera_trigger (UcaCamera *camera, GError **error) -{ -} - -static gboolean -uca_kiro_camera_grab (UcaCamera *camera, gpointer data, GError **error) -{ - g_return_val_if_fail (UCA_IS_KIRO_CAMERA (camera), FALSE); - - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); - - //This is a hack to make sure we actually wait for a new frame; - gpointer frame = kiro_sb_get_data_blocking (priv->receive_buffer); - - kiro_sb_freeze (priv->receive_buffer); - //Element 0 might still be in the process of being written. - //Therefore, we take Element 1, to be sure this one is finished. - if (data) - g_memmove (data, frame, priv->roi_width * priv->roi_height * priv->bytes_per_pixel); - kiro_sb_thaw (priv->receive_buffer); - - return TRUE; -} - - - -// ---------------------------------------------------------- // -// TANGO <-> GLib // -// ---------------------------------------------------------- // -gboolean -unpack_gvaluearray_from_tango (GValue *value, Tango::DeviceAttribute &t_attr, GParamSpec *pspec) -{ - GType value_type = ((GParamSpecValueArray*)pspec)->element_spec->value_type; - if (G_TYPE_UINT != value_type) { - g_print ("Array type attribue '%s' holds elements of type '%s' which can't be handled.\n", pspec->name, g_type_name (value_type) ); - return FALSE; - } - - guint array_length = t_attr.get_dim_x (); - GValueArray *gvalarray = g_value_array_new (array_length); - - //Convenience Macro to prevent either having to rewrite this block - //of code over and over again, or creating two almost identical - // switch-cases... - //UNPACK TANGO GVALUEARRAY - #define __U_T_GVA(__GTYPE, __GFUNC) { \ - vector<__GTYPE> t_vect; \ - t_attr >> t_vect; \ - for (guint idx = 0; idx < array_length; idx++) { \ - g_value_array_append (gvalarray, NULL); \ - GValue *val = g_value_array_get_nth (gvalarray, idx); \ - g_value_init (val, value_type); \ - __GFUNC (val, t_vect[idx]); \ - } \ - } - - switch (value_type) { - case G_TYPE_BOOLEAN: - //We need to to this manualy since there is no implicit conversion from c++ bool to gboolean - { - vector<bool> t_vect; - t_attr >> t_vect; - for (guint idx = 0; idx < array_length; idx++) { - g_value_array_append (gvalarray, NULL); - GValue *val = g_value_array_get_nth (gvalarray, idx); - g_value_init (val, value_type); - g_value_set_boolean (val, (t_vect[idx] ? TRUE : FALSE)); - } - } - break; - case G_TYPE_STRING: - //We need to to this manualy since there is no implicit conversion from c++ string to gchar* - { - vector<string> t_vect; - t_attr >> t_vect; - for (guint idx = 0; idx < array_length; idx++) { - g_value_array_append (gvalarray, NULL); - GValue *val = g_value_array_get_nth (gvalarray, idx); - g_value_init (val, value_type); - g_value_set_string (val, t_vect[idx].c_str ()); - } - } - break; - case G_TYPE_UCHAR: - __U_T_GVA (guchar, g_value_set_uchar); - break; - case G_TYPE_INT: - __U_T_GVA (gint, g_value_set_int); - break; - case G_TYPE_UINT: - __U_T_GVA (guint, g_value_set_uint); - break; - case G_TYPE_INT64: - __U_T_GVA (gint64, g_value_set_int64); - break; - case G_TYPE_UINT64: - __U_T_GVA (guint64, g_value_set_uint64); - break; - case G_TYPE_LONG: - __U_T_GVA (glong, g_value_set_long); - break; - case G_TYPE_ULONG: - __U_T_GVA (gulong, g_value_set_ulong); - break; - case G_TYPE_FLOAT: - __U_T_GVA (gfloat, g_value_set_float); - break; - case G_TYPE_DOUBLE: - __U_T_GVA (gdouble, g_value_set_double); - break; - default: - g_print ("Array type attribue '%s' holds elements of type '%s' which can't be handled.\n", pspec->name, g_type_name (value_type) ); - return FALSE; - } - - g_value_set_boxed_take_ownership (value, gvalarray); - return TRUE; -} - - -void -try_handle_read_tango_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - Tango::DeviceAttribute t_attr; - UcaKiroCamera *camera = UCA_KIRO_CAMERA (object); - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); - - bool property_is_handled = (property_id >= N_PROPERTIES) ? (bool)priv->kiro_dynamic_attributes[property_id] : (bool)kiro_properties[property_id]; - - if (property_is_handled) { - try { - priv->tango_device->read_attribute (pspec->name, t_attr); - } - catch (Tango::DevFailed &e) { - g_warning ("Property '%s' could not be read due to an unexpected TANGO error...\n", pspec->name); - Tango::Except::print_exception (e); - return; - } - - //Stupid workaround for TANGO::State attribute... - //Because they just HAD to make a special case - //for that one specific Enum... - if (0 == g_strcmp0 (pspec->name, "State")) { - Tango::DevState state; - t_attr >> state; - g_value_set_uint (value, (unsigned int)state); - return; - } - - //Convenience Macro to prevent having to write this block - //of code over and over again - #define T_TO_G_CONVERT(GTYPE, T_ATTR, FUNCTION, TARGET) { \ - GTYPE t_val; \ - T_ATTR >> t_val; \ - FUNCTION (TARGET, t_val); \ - } - - // 17.06.2015 - // Somehow the implicit conversions from the glib types to any datatype - // known by TANGO got broken. We need to use the explicit C++ types here - // to make TANGO happy and then rely on the implicit conversion back to - // glib types when the call to g_value_set_XXX occurs... - switch (value->g_type) { - case G_TYPE_FLOAT: - T_TO_G_CONVERT (float, t_attr, g_value_set_float, value); - break; - case G_TYPE_DOUBLE: - T_TO_G_CONVERT (double, t_attr, g_value_set_double, value); - break; - case G_TYPE_UCHAR: - T_TO_G_CONVERT (unsigned char, t_attr, g_value_set_uchar, value); - break; - case G_TYPE_INT: - T_TO_G_CONVERT (short int, t_attr, g_value_set_int, value); - break; - case G_TYPE_UINT: - T_TO_G_CONVERT (unsigned short int, t_attr, g_value_set_uint, value); - break; - case G_TYPE_LONG: - T_TO_G_CONVERT (long int, t_attr, g_value_set_long, value); - break; - case G_TYPE_ULONG: - T_TO_G_CONVERT (unsigned long int, t_attr, g_value_set_ulong, value); - break; - case G_TYPE_INT64: - T_TO_G_CONVERT (int64_t, t_attr, g_value_set_int64, value); - break; - case G_TYPE_UINT64: - T_TO_G_CONVERT (uint64_t, t_attr, g_value_set_uint64, value); - break; - case G_TYPE_BOOLEAN: - { - bool t_val; - t_attr >> t_val; - g_value_set_boolean (value, (t_val ? TRUE : FALSE)); - } - break; - case G_TYPE_STRING: - { - string t_val; - t_attr >> t_val; - g_value_set_string (value, t_val.c_str ()); - } - break; - default: - { - if (g_type_parent (value->g_type) == G_TYPE_ENUM) { - T_TO_G_CONVERT (gint, t_attr, g_value_set_enum, value); - break; - } - - if (G_TYPE_VALUE_ARRAY == value->g_type) { - if (Tango::AttrDataFormat::SPECTRUM != t_attr.get_data_format ()) { - g_warning ("TANGO attribute '%s' is not of type SPECTRUM! (Not a 1-dimensional array, yet libuca was expecting one.)\n", pspec->name); - return; - } - - if (0 == unpack_gvaluearray_from_tango (value, t_attr, pspec)) - g_warning ("Failed to read property '%s'\n", pspec->name); - - return; - } - - GType unhandled = pspec->value_type; - if (G_TYPE_GTYPE == unhandled) { - unhandled = ((GParamSpecGType*)pspec)->is_a_type; - } - g_print ("GType '%s' can't be handled...\n", g_type_name (unhandled)); - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } - } - } - else { - g_print ("Unhandled property...\n"); - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } - -#undef T_TO_G_CONVERT -} - - -gboolean -pack_gvaluearray_to_tango (const GValue *value, Tango::DeviceAttribute &t_attr, GParamSpec *pspec) -{ - - GType value_type = ((GParamSpecValueArray*)pspec)->element_spec->value_type; - GValueArray *gvalarray = (GValueArray *) g_value_get_boxed (value); - guint array_length = gvalarray->n_values; - - //Convenience Macro to prevent either having to rewrite this block - //of code over and over again, or creating two almost identical - // switch-cases... - #define __P_GVA_T(__GTYPE, __GFUNC) { \ - vector<__GTYPE> t_vect (array_length); \ - for (guint idx = 0; idx < array_length; idx++) { \ - GValue *val = g_value_array_get_nth (gvalarray, idx); \ - t_vect[idx] = __GFUNC (val); \ - } \ - t_attr << t_vect; \ - } - - switch (value_type) { - case G_TYPE_BOOLEAN: - __P_GVA_T (bool, g_value_get_boolean); //This relys on the implicit conversion from int to c++ bool - break; - case G_TYPE_UCHAR: - __P_GVA_T (guchar, g_value_get_uchar); - break; - case G_TYPE_STRING: - __P_GVA_T (string, g_value_get_string); //This relys on the implicit conversion from char* to c++ string - break; - case G_TYPE_INT: - __P_GVA_T (gint, g_value_get_int); - break; - case G_TYPE_UINT: - __P_GVA_T (guint, g_value_get_uint); - break; - case G_TYPE_INT64: - __P_GVA_T (gint64, g_value_get_int64); - break; - case G_TYPE_UINT64: - __P_GVA_T (guint64, g_value_get_uint64); - break; - case G_TYPE_LONG: - __P_GVA_T (glong, g_value_get_long); - break; - case G_TYPE_ULONG: - __P_GVA_T (gulong, g_value_get_ulong); - break; - case G_TYPE_FLOAT: - __P_GVA_T (gfloat, g_value_get_float); - break; - case G_TYPE_DOUBLE: - __P_GVA_T (gdouble, g_value_get_double); - break; - default: - g_print ("Array type attribue '%s' holds elements of type '%s' which can't be handled.\n", pspec->name, g_type_name (value_type) ); - return FALSE; - } - - t_attr.data_format = Tango::AttrDataFormat::SPECTRUM; - t_attr.dim_x = array_length; - return TRUE; - -#undef __P_GVA_T -} - - -void -try_handle_write_tango_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - Tango::DeviceAttribute t_attr; - UcaKiroCamera *camera = UCA_KIRO_CAMERA (object); - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (camera); - - bool property_is_handled = (property_id > N_PROPERTIES) ? (bool)priv->kiro_dynamic_attributes[property_id] : (bool)kiro_properties[property_id]; - - if (property_is_handled) { - - // 17.06.2015 - // Implicit conversions from glib types to TANGO C++ types are broken. - // We need to to a manual cast for each one to make TANGO happy again... - switch (value->g_type) { - case G_TYPE_BOOLEAN: - { - bool t_val = (g_value_get_boolean (value) == TRUE); - t_attr << t_val; - } - break; - case G_TYPE_INT: - t_attr << (int)g_value_get_int (value); - break; - case G_TYPE_FLOAT: - t_attr << (float)g_value_get_float (value); - break; - case G_TYPE_DOUBLE: - t_attr << (double)g_value_get_double (value); - break; - case G_TYPE_UINT: - t_attr << (unsigned short int)g_value_get_uint (value); - break; - case G_TYPE_ULONG: - t_attr << (unsigned long int)g_value_get_ulong (value); - break; - case G_TYPE_STRING: - t_attr << g_value_get_string (value); - break; - case G_TYPE_UCHAR: - t_attr << (unsigned char)g_value_get_uchar (value); - break; - case G_TYPE_INT64: - t_attr << (int64_t)g_value_get_int64 (value); - break; - case G_TYPE_UINT64: - t_attr << (uint64_t)g_value_get_uint64 (value); - break; - case G_TYPE_LONG: - t_attr << (long int)g_value_get_long (value); - break; - case G_TYPE_ENUM: - t_attr << g_value_get_enum (value); - break; - default: - { - if (g_type_parent (value->g_type) == G_TYPE_ENUM) { - t_attr << g_value_get_enum (value); - break; - } - - if (value->g_type == G_TYPE_VALUE_ARRAY) { - if (0 == pack_gvaluearray_to_tango (value, t_attr, pspec)) { - g_warning ("Failed to write property '%s'.\n", pspec->name); - return; - } - break; - } - - GType unhandled = value->g_type; - if (G_TYPE_GTYPE == unhandled) { - unhandled = ((GParamSpecGType*)pspec)->is_a_type; - } - g_print ("GType '%s' can't be handled...\n", g_type_name (unhandled)); - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } - break; - } - - t_attr.set_name (pspec->name); - - try { - priv->tango_device->write_attribute (t_attr); - } - catch (Tango::DevFailed &e) { - g_warning ("Property '%s' could not be written due to a TANGO exception: '%s'\n", pspec->name, (const char *)e.errors[0].desc); - Tango::Except::print_exception (e); - return; - } - } - else - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - - -GType -gtype_from_tango_type (Tango::CmdArgType t) -{ - using namespace Tango; - switch (t) { - case DEV_VOID: - return G_TYPE_NONE; - case DEV_BOOLEAN: - return G_TYPE_BOOLEAN; - case DEV_SHORT: - //Fall-through intentional - case DEV_INT: - //Fall-through intentional - case DEV_LONG: - return G_TYPE_INT; - case DEV_FLOAT: - return G_TYPE_FLOAT; - case DEV_DOUBLE: - return G_TYPE_DOUBLE; - case DEV_ULONG: - //return G_TYPE_ULONG; - //Fall-through intentional - //NOTE: There seems to be a bug somewhere either in TANGO or in GLib or in Pyhton that - //Breaks the functionality of the G_TYPE_ULONG properties. Using a G_TYPE_UINT instead - //works around this problem but might provoke potential overflows... - case DEV_USHORT: - return G_TYPE_UINT; - case CONST_DEV_STRING: - //Fall-through intentional - case DEV_STRING: - return G_TYPE_STRING; - case DEV_UCHAR: - return G_TYPE_UCHAR; - case DEV_LONG64: - return G_TYPE_INT64; - case DEV_ULONG64: - return G_TYPE_UINT64; - case DEV_STATE: - return G_TYPE_UINT; - /* - DEV_ENCODED - DEVVAR_CHARARRAY - DEVVAR_SHORTARRAY - DEVVAR_LONGARRAY - DEVVAR_FLOATARRAY - DEVVAR_DOUBLEARRAY - DEVVAR_USHORTARRAY - DEVVAR_ULONGARRAY - DEVVAR_STRINGARRAY - DEVVAR_LONGSTRINGARRAY - DEVVAR_DOUBLESTRINGARRAY - DEVVAR_BOOLEANARRAY - DEVVAR_LONG64ARRAY - DEVVAR_ULONG64ARRAY - */ - default: - return G_TYPE_INVALID; - }; -} - - -gint -get_property_id_from_name(const gchar* name) -{ - guint idx = 0; - gboolean found = FALSE; - for (;idx < N_PROPERTIES; ++idx) { - if (0 == g_strcmp0(name, uca_camera_props[idx])) { - found = TRUE; - break; - } - } - return (TRUE == found) ? idx : -1; -} - - -void -build_param_spec(GParamSpec **pspec, const Tango::AttributeInfoEx *attrInfo) -{ - GType type = gtype_from_tango_type ((Tango::CmdArgType)attrInfo->data_type); - const gchar *name = attrInfo->name.c_str (); - GParamFlags flags = G_PARAM_READABLE; - if (attrInfo->writable == Tango::AttrWriteType::WRITE) - flags = (GParamFlags) G_PARAM_READWRITE; - - - //Convenience Macro to prevent having to rewrite this block - //of code over and over again.. - #define __M_PSCPEC(__SPEC_TYPE, __LIMITS_1, __LIMITS_2, __LIMITS_3) { \ - *pspec = \ - __SPEC_TYPE (name, \ - attrInfo->description.c_str (), \ - g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL), \ - __LIMITS_1, __LIMITS_2, __LIMITS_3,\ - flags); \ - } - - switch (type) { - case G_TYPE_INT: - __M_PSCPEC (g_param_spec_int, G_MININT32, G_MAXINT32, 0); - break; - case G_TYPE_FLOAT: - __M_PSCPEC (g_param_spec_float, G_MINFLOAT, G_MAXFLOAT, 0.); - break; - case G_TYPE_DOUBLE: - __M_PSCPEC (g_param_spec_double, G_MINDOUBLE, G_MAXDOUBLE, 0.) - break; - case G_TYPE_UINT: - __M_PSCPEC (g_param_spec_uint, 0, G_MAXUINT, 0) - break; - case G_TYPE_ULONG: - __M_PSCPEC (g_param_spec_ulong, 0, G_MAXULONG, 0) - break; - case G_TYPE_UCHAR: - __M_PSCPEC (g_param_spec_uchar, 0x00, 0xff, 0x42) - break; - case G_TYPE_INT64: - __M_PSCPEC (g_param_spec_int64, G_MININT64, G_MAXINT64, 0) - break; - case G_TYPE_UINT64: - __M_PSCPEC (g_param_spec_uint64, 0, G_MAXUINT64, 0) - break; - case G_TYPE_LONG: - __M_PSCPEC (g_param_spec_long, G_MININT64, G_MAXINT64, 1) - break; - case G_TYPE_ENUM: - __M_PSCPEC (g_param_spec_int, 0, G_MAXUINT, 0) - break; - case G_TYPE_STRING: - *pspec = - g_param_spec_string (name, - attrInfo->description.c_str (), - g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL), - "DEFAULT", - flags); - break; - case G_TYPE_BOOLEAN: - *pspec = - g_param_spec_boolean (name, - attrInfo->description.c_str (), - g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL), - FALSE, - flags); - break; - default: - *pspec = - g_param_spec_gtype (name, - attrInfo->description.c_str (), - g_strconcat ("KIRO TANGO <-> GLib interface of ", name, NULL), - type, - flags); - } - -#undef __M_PSCPEC -} - - -void -uca_kiro_camera_clone_interface(const gchar* address, UcaKiroCamera *kiro_camera) -{ - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (kiro_camera); - UcaKiroCameraClass *klass = UCA_KIRO_CAMERA_GET_CLASS (kiro_camera); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gboolean start_found, stop_found, readout_found, unit_found = FALSE; - - try { - Tango::CommandInfoList *cmd_list = priv->tango_device->command_list_query (); - for (vector<Tango::CommandInfo>::iterator iter = cmd_list->begin (); iter != cmd_list->end (); ++iter) { - gint start_cmp = g_strcmp0((*iter).cmd_name.c_str (), "StartRecording"); - if (0 == start_cmp) { - start_found = TRUE; - } - gint stop_cmp = g_strcmp0 ((*iter).cmd_name.c_str (), "StopRecording"); - if (0 == stop_cmp) { - stop_found = TRUE; - } - gint unit_cmp = g_strcmp0((*iter).cmd_name.c_str (), "GetAttributeUnit"); - if (0 == unit_cmp) { - unit_found = TRUE; - } - gint readout_cmp = g_strcmp0((*iter).cmd_name.c_str (), "Readout"); - if (0 == readout_cmp) { - readout_found = TRUE; - } - } - - if ( !start_found || !stop_found ) { - g_warning ("The Server at '%s' does not provide the necessary 'StartRecording' and 'StopRecording' interface\n", priv->kiro_tango_address); - g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_BAD_CAMERA_INTERFACE, - "The Server at '%s' does not provide the necessary 'StartRecording' and 'StopRecording' interface\n", priv->kiro_tango_address); - priv->construction_error = TRUE; - return; - } - - vector<string> *attr_list = priv->tango_device->get_attribute_list (); - GList *non_base_attributes = NULL; - guint non_base_attributes_count = 0; - - for (vector<string>::iterator iter = attr_list->begin (); iter != attr_list->end (); ++iter) { - Tango::AttributeInfoEx attrInfo = priv->tango_device->attribute_query (*iter); - gint uca_base_prop_id = get_property_id_from_name ((*iter).c_str ()); - if (-1 < uca_base_prop_id) { - guint is_name_attr = g_strcmp0 ((*iter).c_str (), "name"); - if (0 == is_name_attr) { - Tango::DeviceAttribute t_attr; - priv->tango_device->read_attribute ("name", t_attr); - string reply_name; - t_attr >> reply_name; - g_free (priv->remote_name); - priv->remote_name = g_strdup (reply_name.c_str ()); - } - kiro_properties[uca_base_prop_id] = g_object_class_find_property (gobject_class, uca_camera_props[uca_base_prop_id]); - g_object_class_override_property(G_OBJECT_CLASS (UCA_KIRO_CAMERA_GET_CLASS (kiro_camera)), uca_base_prop_id, uca_camera_props[uca_base_prop_id]); - } - else { - non_base_attributes = g_list_append (non_base_attributes, (gpointer)(*iter).c_str ()); - non_base_attributes_count++; - } - } - - if (non_base_attributes_count > 0) { - priv->kiro_dynamic_attributes = new GParamSpec* [N_PROPERTIES + non_base_attributes_count]; - UcaKiroCameraClass *klass = UCA_KIRO_CAMERA_GET_CLASS (kiro_camera); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - for (guint idx = 0; idx < non_base_attributes_count; idx++) { - const gchar *attr_name = (const gchar*)g_list_nth_data (non_base_attributes, idx); - Tango::AttributeInfoEx attrInfo = priv->tango_device->attribute_query (string(attr_name)); - - if (Tango::AttrDataFormat::IMAGE == attrInfo.data_format || Tango::AttrDataFormat::FMT_UNKNOWN == attrInfo.data_format) { - g_print ("Attribute '%s' has unknown DataFormat. Skipping.\n", attr_name); - continue; - } - - build_param_spec (&(priv->kiro_dynamic_attributes[N_PROPERTIES + idx]), &attrInfo); - g_object_class_install_property (gobject_class, N_PROPERTIES + idx, priv->kiro_dynamic_attributes[N_PROPERTIES + idx]); - - if (unit_found) { - Tango::DeviceData arg_name; - arg_name << attr_name; - Tango::DeviceData cmd_reply = priv->tango_device->command_inout("GetAttributeUnit", arg_name); - gint unit; - cmd_reply >> unit; - uca_camera_register_unit (UCA_CAMERA (kiro_camera), attr_name, (UcaUnit)unit); - } - } - } - } - catch (Tango::DevFailed &e) { - Tango::Except::print_exception (e); - g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, - "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc); - priv->construction_error = TRUE; - } -} -// ---------------------------------------------------------- // -// END: TANGO <-> GLib // -// ---------------------------------------------------------- // - - - -static void -uca_kiro_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) -{ - g_return_if_fail(UCA_IS_KIRO_CAMERA (object)); - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (object); - - switch (property_id) { - case PROP_KIRO_TANGO_ADDRESS: - priv->kiro_tango_address = g_value_dup_string (value); - break; - default: - try_handle_write_tango_property (object, property_id, value, pspec); - return; - } -} - - -static void -uca_kiro_camera_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) -{ - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (object); - - switch (property_id) { - case PROP_NAME: - g_value_set_string (value, "KIRO camera"); - break; - case PROP_KIRO_ADDRESS: - g_value_set_string (value, priv->kiro_address); - break; - case PROP_KIRO_PORT: - g_value_set_uint (value, priv->kiro_port_uint); - break; - case PROP_KIRO_TANGO_ADDRESS: - g_value_set_string (value, priv->kiro_tango_address); - break; - case PROP_KIRO_REMOTE_NAME: - g_value_set_string (value, priv->remote_name); - break; - default: - try_handle_read_tango_property (object, property_id, value, pspec); - break; - } -} - -static void -uca_kiro_camera_finalize(GObject *object) -{ - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE(object); - - if (priv->thread_running) { - priv->thread_running = FALSE; - g_thread_join (priv->grab_thread); - } - - if (priv->receive_buffer) { - kiro_sb_free (priv->receive_buffer); - priv->receive_buffer = NULL; - } - priv->kiro_connected = FALSE; - - if (priv->dummy_data) { - g_free (priv->dummy_data); - priv->dummy_data = NULL; - } - - if (priv->tango_device) { - delete (priv->tango_device); - priv->tango_device = NULL; - } - - g_free (priv->kiro_address); - g_free (priv->kiro_port); - g_free (priv->kiro_tango_address); - - G_OBJECT_CLASS (uca_kiro_camera_parent_class)->finalize(object); -} - -static gboolean -ufo_kiro_camera_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - g_return_val_if_fail (UCA_IS_KIRO_CAMERA (initable), FALSE); - - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (UCA_KIRO_CAMERA (initable)); - if(priv->construction_error) { - g_propagate_error (error, initable_iface_error); - return FALSE; - } - - return TRUE; -} - -static void -uca_kiro_initable_iface_init (GInitableIface *iface) -{ - iface->init = ufo_kiro_camera_initable_init; -} - -static void -uca_kiro_camera_constructed (GObject *object) -{ - //Initialization for the KIRO Server and TANGO Interface cloning is moved - //here and done early! - //We want to add dynamic properties and it is too late to do so in the - //real initable part. Therefore, we do it here and 'remember' any errors - //that occur and check them later in the initable part. - - UcaKiroCamera *self = UCA_KIRO_CAMERA (object); - UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (self); - - GValue address = G_VALUE_INIT; - g_value_init(&address, G_TYPE_STRING); - uca_kiro_camera_get_property (object, PROP_KIRO_TANGO_ADDRESS, &address, NULL); - gint address_not_none = g_strcmp0(g_value_get_string (&address), "NONE"); - if (0 == address_not_none) { - g_warning ("kiro-tango-address was not set! Can not connect to server...\n"); - priv->construction_error = TRUE; - g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_MISSING_TANGO_ADDRESS, - "'kiro-tango-address' property was not set during construction."); - } - else { - try { - priv->tango_device = new Tango::DeviceProxy(g_value_get_string (&address)); - Tango::DbData kiro_credentials; - kiro_credentials.push_back (Tango::DbDatum("KiroAddress")); - kiro_credentials.push_back (Tango::DbDatum("KiroPort")); - priv->tango_device->get_property(kiro_credentials); - string kiro_address, kiro_port; - kiro_credentials[0] >> kiro_address; - kiro_credentials[1] >> kiro_port; - - if (0 > kiro_sb_clone (priv->receive_buffer, kiro_address.c_str (), kiro_port.c_str ())) { - g_warning ("Unable to connect to server at address: %s, port: %s\n", kiro_address.c_str (), kiro_port.c_str ()); - priv->construction_error = TRUE; - g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED, - "Failed to establish a KIRO InfiniBand connection."); - } - else { - priv->kiro_connected = TRUE; - uca_kiro_camera_clone_interface (g_value_get_string (&address), self); - } - } - catch (Tango::DevFailed &e) { - Tango::Except::print_exception (e); - g_set_error (&initable_iface_error, UCA_KIRO_CAMERA_ERROR, UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, - "A TANGO exception was raised: '%s'", (const char *)e.errors[0].desc); - priv->construction_error = TRUE; - } - } - - G_OBJECT_CLASS (uca_kiro_camera_parent_class)->constructed(object); -} - - - -static void -uca_kiro_camera_class_init(UcaKiroCameraClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS( klass); - gobject_class->set_property = uca_kiro_camera_set_property; - gobject_class->get_property = uca_kiro_camera_get_property; - gobject_class->finalize = uca_kiro_camera_finalize; - gobject_class->constructed = uca_kiro_camera_constructed; - - UcaCameraClass *camera_class = UCA_CAMERA_CLASS (klass); - camera_class->start_recording = uca_kiro_camera_start_recording; - camera_class->stop_recording = uca_kiro_camera_stop_recording; - camera_class->grab = uca_kiro_camera_grab; - camera_class->trigger = uca_kiro_camera_trigger; - - for (guint i = 0; kiro_overrideables[i] != 0; i++) - g_object_class_override_property (gobject_class, kiro_overrideables[i], uca_camera_props[kiro_overrideables[i]]); - - kiro_properties[PROP_KIRO_ADDRESS] = - g_param_spec_string("kiro-address", - "KIRO Server Address", - "Address of the KIRO Server to grab images from", - "NONE", - G_PARAM_READABLE); - - kiro_properties[PROP_KIRO_PORT] = - g_param_spec_uint("kiro-port", - "KIRO Server Port", - "Port of the KIRO Server to grab images from", - 1, 65535, 60010, - G_PARAM_READABLE); - - kiro_properties[PROP_KIRO_TANGO_ADDRESS] = - g_param_spec_string("kiro-tango-address", - "KIRO TANGO address", - "Address of the KIRO Server in the TANGO environment", - "NONE", - (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - kiro_properties[PROP_KIRO_REMOTE_NAME] = - g_param_spec_string("remote-name", - "Name of the remot camera", - "Name of the camera plugin that is loaded on the KIRO remote site", - "NONE", - G_PARAM_READABLE); - - for (guint id = N_BASE_PROPERTIES; id < N_PROPERTIES; id++) - g_object_class_install_property (gobject_class, id, kiro_properties[id]); - - g_type_class_add_private (klass, sizeof(UcaKiroCameraPrivate)); -} - -static void -uca_kiro_camera_init(UcaKiroCamera *self) -{ - self->priv = UCA_KIRO_CAMERA_GET_PRIVATE(self); - self->priv->grab_thread = NULL; - self->priv->current_frame = 0; - self->priv->kiro_address = g_strdup ("NONE"); - self->priv->kiro_port = g_strdup ("NONE"); - self->priv->remote_name = g_strdup ("NONE"); - self->priv->kiro_port_uint = 60010; - self->priv->kiro_tango_address = g_strdup ("NONE"); - self->priv->construction_error = FALSE; - self->priv->kiro_dynamic_attributes = NULL; - - self->priv->receive_buffer = kiro_sb_new (); - kiro_sb_freeze (self->priv->receive_buffer); -} - - -G_MODULE_EXPORT GType -uca_camera_get_type (void) -{ - return UCA_TYPE_KIRO_CAMERA; -} - diff --git a/src/uca-kiro-camera.h b/src/uca-kiro-camera.h index b1b9d42..a84e574 100644 --- a/src/uca-kiro-camera.h +++ b/src/uca-kiro-camera.h @@ -19,7 +19,8 @@ #define __UCA_KIRO_CAMERA_H #include <glib-object.h> -#include "uca-camera.h" +#include "uca/uca-camera.h" +#include "kiro/kiro-messenger.h" G_BEGIN_DECLS @@ -35,11 +36,9 @@ G_BEGIN_DECLS GQuark uca_kiro_camera_error_quark(void); typedef enum { - UCA_KIRO_CAMERA_ERROR_MISSING_TANGO_ADDRESS = UCA_CAMERA_ERROR_END_OF_STREAM, - UCA_KIRO_CAMERA_ERROR_TANGO_CONNECTION_FAILED, - UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED, - UCA_KIRO_CAMERA_ERROR_TANGO_EXCEPTION_OCCURED, - UCA_KIRO_CAMERA_ERROR_BAD_CAMERA_INTERFACE + UCA_KIRO_CAMERA_ERROR_MISSING_ADDRESS = UCA_CAMERA_ERROR_END_OF_STREAM, + UCA_KIRO_CAMERA_ERROR_ADDRESS_WRONG_FORMAT, + UCA_KIRO_CAMERA_ERROR_KIRO_CONNECTION_FAILED } UcaKiroCameraError; @@ -74,7 +73,326 @@ struct _UcaKiroCameraClass { G_END_DECLS -void uca_kiro_camera_clone_interface (const gchar* address, UcaKiroCamera *kiro_camera); +//HELPER FUNCTIONS AND CONSTRUCTS FOR SERVER AND CAMERA PLUGIN +typedef enum { + KIROCS_UPDATE, + KIROCS_INSTALL, + KIROCS_READY, + KIROCS_RPC, + KIROCS_EXIT +}KiroCsCommands; + +typedef struct { + guint32 id; + guint32 size; + gboolean scalar; + gchar type[2]; + gchar val[1]; +} PropUpdate; + +typedef struct { + guint32 str_len; + gchar str[1]; +}StrProp; + +typedef struct { + GType value_type; + guint32 name_len; + union PSpecs { + GParamSpecBoolean bool_spec; + GParamSpecChar char_spec; + GParamSpecInt int_spec; + GParamSpecUInt uint_spec; + GParamSpecLong long_spec; + GParamSpecULong ulong_spec; + GParamSpecInt64 int64_spec; + GParamSpecUInt64 uint64_spec; + GParamSpecFloat float_spec; + GParamSpecDouble double_spec; + StrProp str_spec; + } spec; + gchar name[1]; +} PropertyRequisition; + + +//Forward declaration of the trigger enums for type handling +GType uca_camera_trigger_source_get_type (void) G_GNUC_CONST; +#define UCA_TYPE_CAMERA_TRIGGER_SOURCE (uca_camera_trigger_source_get_type ()) +GType uca_camera_trigger_type_get_type (void) G_GNUC_CONST; +#define UCA_TYPE_CAMERA_TRIGGER_TYPE (uca_camera_trigger_type_get_type ()) + + +gchar +gtype_to_gvariant_class (GType type) +{ + gchar ret = '*'; + + switch (type) { + case G_TYPE_BOOLEAN: + ret = G_VARIANT_CLASS_BOOLEAN; + break; + case G_TYPE_CHAR: + ret = G_VARIANT_CLASS_BYTE; + break; + case G_TYPE_INT: + ret = G_VARIANT_CLASS_INT32; + break; + case G_TYPE_ENUM: + ret = G_VARIANT_CLASS_INT32; + break; + case G_TYPE_UINT: + ret = G_VARIANT_CLASS_UINT32; + break; + case G_TYPE_LONG: + ret = G_VARIANT_CLASS_INT64; + break; + case G_TYPE_ULONG: + ret = G_VARIANT_CLASS_UINT64; + break; + case G_TYPE_INT64: + ret = G_VARIANT_CLASS_INT64; + break; + case G_TYPE_UINT64: + ret = G_VARIANT_CLASS_UINT64; + break; + case G_TYPE_FLOAT: + ret = G_VARIANT_CLASS_DOUBLE; + break; + case G_TYPE_DOUBLE: + ret = G_VARIANT_CLASS_DOUBLE; + break; + default: + //ERROR + break; + } + + return ret; +} + + +#define GOBJECT_SET(OBJ, PROP, TYPE, DATA) { \ + g_object_set (OBJ, \ + PROP, *(TYPE *)DATA, \ + NULL); \ +} + +void +update_property_scalar (GObject *cam, const gchar *prop, GType type, gulong handler, gpointer data) +{ + g_debug ("Updating %s, with handler %lu", prop, handler); + + g_signal_handler_block (cam, handler); + + switch (type) { + case G_TYPE_BOOLEAN: + GOBJECT_SET (cam, prop, gboolean, data); + break; + case G_TYPE_CHAR: + GOBJECT_SET (cam, prop, gchar, data); + break; + case G_TYPE_INT: + GOBJECT_SET (cam, prop, gint, data); + break; + case G_TYPE_ENUM: + GOBJECT_SET (cam, prop, gint, data); + break; + case G_TYPE_UINT: + GOBJECT_SET (cam, prop, guint, data); + break; + case G_TYPE_LONG: + GOBJECT_SET (cam, prop, glong, data); + break; + case G_TYPE_ULONG: + GOBJECT_SET (cam, prop, gulong, data); + break; + case G_TYPE_INT64: + GOBJECT_SET (cam, prop, gint64, data); + break; + case G_TYPE_UINT64: + GOBJECT_SET (cam, prop, guint64, data); + break; + case G_TYPE_FLOAT: + GOBJECT_SET (cam, prop, gfloat, data); + break; + case G_TYPE_DOUBLE: + GOBJECT_SET (cam, prop, gdouble, data); + break; + default: + //TRIGGER_TYPE and TRIGGER_SOURCE are not statically typed and can + //not be used in a switch statement... + if (type == UCA_TYPE_CAMERA_TRIGGER_SOURCE) { + GOBJECT_SET (cam, prop, gint, data); + break; + } + + if (type == UCA_TYPE_CAMERA_TRIGGER_TYPE) { + GOBJECT_SET (cam, prop, gint, data); + break; + } + + g_critical ("Type %s not handled! (SET)", g_type_name (type)); + break; + } + + g_signal_handler_unblock (cam, handler); +} + + +#define GOBJECT_GET(OBJ, PROP, TYPE, GTYPE) { \ + TYPE tmp; \ + gchar *gvclass = g_malloc0 (2); \ + gvclass[0] = gtype_to_gvariant_class (GTYPE); \ + g_object_get (OBJ, \ + PROP, &tmp, \ + NULL); \ + ret = g_variant_new (gvclass, tmp); \ + g_free (gvclass); \ +} + +GVariant* +read_property_scalar (GObject *cam, const gchar *prop, GType type) +{ + GVariant *ret = NULL; + + switch (type) { + case G_TYPE_BOOLEAN: + GOBJECT_GET (cam, prop, gboolean, type); + break; + case G_TYPE_CHAR: + GOBJECT_GET (cam, prop, gchar, type); + break; + case G_TYPE_INT: + GOBJECT_GET (cam, prop, gint, type); + break; + case G_TYPE_ENUM: + GOBJECT_GET (cam, prop, gint, type); + break; + case G_TYPE_UINT: + GOBJECT_GET (cam, prop, guint, type); + break; + case G_TYPE_LONG: + GOBJECT_GET (cam, prop, glong, type); + break; + case G_TYPE_ULONG: + GOBJECT_GET (cam, prop, gulong, type); + break; + case G_TYPE_INT64: + GOBJECT_GET (cam, prop, gint64, type); + break; + case G_TYPE_UINT64: + GOBJECT_GET (cam, prop, guint64, type); + break; + case G_TYPE_FLOAT: + GOBJECT_GET (cam, prop, gfloat, type); + break; + case G_TYPE_DOUBLE: + GOBJECT_GET (cam, prop, gdouble, type); + break; + default: + //TRIGGER_TYPE and TRIGGER_SOURCE are not statically typed and can + //not be used in a switch statement... + if (type == UCA_TYPE_CAMERA_TRIGGER_SOURCE) { + GOBJECT_GET (cam, prop, gint, type); + break; + } + + if (type == UCA_TYPE_CAMERA_TRIGGER_TYPE) { + GOBJECT_GET (cam, prop, gint, type); + break; + } + + g_critical ("Type %s not handled! (GET)", g_type_name (type)); + break; + } + + return ret; +} + + + +#define GVALUE_TO_GVARIANT(VALUE, FUNC, TYPE, GTYPE) { \ + TYPE tmp; \ + gchar *gvclass = g_malloc0 (2); \ + gvclass[0] = gtype_to_gvariant_class (GTYPE); \ + tmp = FUNC (VALUE); \ + ret = g_variant_new (gvclass, tmp); \ + g_free (gvclass); \ +} + +GVariant* +variant_from_scalar (GValue *value) +{ + GVariant *ret = NULL; + + GType type = G_VALUE_TYPE (value); + + switch (type) { + case G_TYPE_BOOLEAN: + GVALUE_TO_GVARIANT (value, g_value_get_boolean, gboolean, type); + break; + case G_TYPE_CHAR: + GVALUE_TO_GVARIANT (value, g_value_get_char, gchar, type); + break; + case G_TYPE_INT: + GVALUE_TO_GVARIANT (value, g_value_get_int, gint, type); + break; + case G_TYPE_ENUM: + GVALUE_TO_GVARIANT (value, g_value_get_int, gint, type); + break; + case G_TYPE_UINT: + GVALUE_TO_GVARIANT (value, g_value_get_uint, guint, type); + break; + case G_TYPE_LONG: + GVALUE_TO_GVARIANT (value, g_value_get_long, glong, type); + break; + case G_TYPE_ULONG: + GVALUE_TO_GVARIANT (value, g_value_get_ulong, gulong, type); + break; + case G_TYPE_INT64: + GVALUE_TO_GVARIANT (value, g_value_get_int64, gint64, type); + break; + case G_TYPE_UINT64: + GVALUE_TO_GVARIANT (value, g_value_get_uint64, guint64, type); + break; + case G_TYPE_FLOAT: + GVALUE_TO_GVARIANT (value, g_value_get_float, gfloat, type); + break; + case G_TYPE_DOUBLE: + GVALUE_TO_GVARIANT (value, g_value_get_double, gdouble, type); + break; + default: + //TRIGGER_TYPE and TRIGGER_SOURCE are not statically typed and can + //not be used in a switch statement... + if (type == UCA_TYPE_CAMERA_TRIGGER_SOURCE) { + GVALUE_TO_GVARIANT (value, g_value_get_int, gint, type); + break; + } + + if (type == UCA_TYPE_CAMERA_TRIGGER_TYPE) { + GVALUE_TO_GVARIANT (value, g_value_get_int, gint, type); + break; + } + + g_critical ("Type %s not handled! (GET)", g_type_name (type)); + break; + } + + return ret; +} + +gint +property_id_from_name(const gchar* name) +{ + gint idx = 0; + gboolean found = FALSE; + for (;idx < N_BASE_PROPERTIES; ++idx) { + if (0 == g_strcmp0(name, uca_camera_props[idx])) { + found = TRUE; + break; + } + } + return found ? idx : -1; +} #endif |