From 786627dcef84c34780a04ca0c856c78132003bc2 Mon Sep 17 00:00:00 2001 From: Timo Dritschler Date: Fri, 21 Aug 2015 17:31:50 +0200 Subject: WIP for camera server and plugin - Scalar property exchange works - Setup of non-base scalar properties works - Some few RPC lines of coded added - Non-scalars are not supported yet - Non-scalar, non-base, property setup is not supported yet - RPC is waiting for KiroMessenger to support static RDMA --- bin/CMakeLists.txt | 4 +- bin/kiro-camera-server.c | 203 ++++++++++++++++++++++++++++++---------------- src/uca-kiro-camera.c | 205 +++++++++++++++++++++++++++++++++++++---------- src/uca-kiro-camera.h | 158 +++++++++++++++++++++++++++++++++--- 4 files changed, 442 insertions(+), 128 deletions(-) diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index acdc243..29e077c 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -4,7 +4,7 @@ link_directories(${KIROCS_BINARY_DIR}) add_executable(kiro-camera-server kiro-camera-server.c) target_link_libraries(kiro-camera-server ${KIROCS_DEPS}) -add_executable(test-camera-server test-server.c) -target_link_libraries(test-camera-server ${KIROCS_DEPS}) +#add_executable(test-camera-server test-server.c) +#target_link_libraries(test-camera-server ${KIROCS_DEPS}) install(TARGETS kiro-camera-server RUNTIME DESTINATION ${KIROCS_BINDIR}) diff --git a/bin/kiro-camera-server.c b/bin/kiro-camera-server.c index 80683ac..839c637 100644 --- a/bin/kiro-camera-server.c +++ b/bin/kiro-camera-server.c @@ -19,6 +19,7 @@ #include #include +#include #include "uca-kiro-camera.h" #include "uca/uca-plugin-manager.h" @@ -30,6 +31,8 @@ typedef struct { gulong peer_rank; gulong *signal_handlers; GParamSpec **properties; + guint n_properties; + KiroRequest *peer_update_request; } KiroCsData; @@ -70,7 +73,7 @@ pspec_size (GType type) ret = sizeof (GParamSpecDouble); break; default: - ret = sizeof (GParamSpec); + ret = sizeof (GParamSpec); } return ret; @@ -132,36 +135,51 @@ print_cam_name (gchar *name, gpointer unused) } +static void +send_clear_callback (KiroRequest *request, gpointer data) +{ + (void) data; + if (request->status != KIRO_MESSAGE_SEND_SUCCESS) + g_error ("OH SHIT!"); + else + g_debug ("Peer informed successfully"); + + if (request->message->payload) + g_free (request->message->payload); + g_free (request->message); + g_free (request); +} + + static void peer_inform_update (UcaCamera *cam, GParamSpec *pspec, KiroCsData *data) { - g_print ("Updated %s.\n", pspec->name); + g_print ("Updated %s.\n", pspec->name); - GError *error = NULL; + gpointer buff = g_malloc0 (sizeof (guint64)); + g_object_get (G_OBJECT (cam), + pspec->name, buff, + NULL); - GVariant *tmp = read_property_scalar (G_OBJECT (cam), pspec->name, pspec->value_type); - gsize data_size = g_variant_get_size (tmp); + KiroMessage *message = g_malloc0 (sizeof (KiroMessage)); + message->msg = KIROCS_UPDATE; + message->size = sizeof (PropUpdateScalar); + message->payload = g_malloc0 (message->size); - PropUpdate *test = g_malloc0 (sizeof (PropUpdate) + data_size); - test->id = property_id_from_name (pspec->name); - test->type[0] = gtype_to_gvariant_class (pspec->value_type); - test->size = data_size; - g_variant_store (tmp, test->val); - g_variant_unref (tmp); + PropUpdateScalar *update = message->payload; + update->base.id = property_id_from_name (pspec->name, data->n_properties, data->properties); + update->base.size = 1; + update->base.scalar = TRUE; - KiroMessage message; - message.peer_rank = data->peer_rank; - message.msg = KIROCS_UPDATE; - message.payload = test; - message.size = sizeof (PropUpdate) + data_size; + memcpy (&update->prop_raw, buff, sizeof (guint64)); - kiro_messenger_send_blocking (data->messenger, &message, &error); + GError *error = NULL; + kiro_messenger_send_blocking (data->messenger, message, data->peer_rank, &error); if (error) { - g_free (test); + g_free (message); g_error ("Oh shit! (%s)", error->message); + g_error_free (error); } - - g_free (test); } @@ -176,26 +194,6 @@ setup_signal_handler (UcaCamera *cam, GParamSpec *pspec, KiroCsData *data) } -static void -null_callback (gpointer unused) -{ - (void)unused; -} - - -static inline gpointer -unpack_scalar (PropUpdate *src) -{ - //Alloc max scalar size - gpointer out = g_malloc0 (sizeof (guint64)); - - GVariant *var = g_variant_new_from_data ((const GVariantType *)src->type, src->val, \ - src->size, TRUE, null_callback, NULL); - g_variant_get (var, src->type, out); - g_variant_unref (var); - return out; -} - static KiroContinueFlag connect_callback (gulong rank, gulong *storage) { @@ -205,36 +203,70 @@ connect_callback (gulong rank, gulong *storage) // MAIN HANDLER // -static KiroContinueFlag -receive_callback (KiroMessageStatus *status, KiroCsData *data) +static void +receive_callback (KiroRequest *request, KiroCsData *data) { - if (status->message->msg == KIROCS_EXIT) { + if (request->message->msg == KIROCS_EXIT) { g_message ("Peer requested shut down..."); data->exit_flag = TRUE; } - 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); + if (request->message->msg == KIROCS_UPDATE) { + PropUpdate *update = (PropUpdate *)request->message->payload; + g_signal_handler_block (data->cam, data->signal_handlers[update->id]); //Don't forget the -1, because the index starts at 0, but property IDs //start at 1... - update_property_scalar (G_OBJECT (data->cam), - data->properties[update->id -1]->name, - data->properties[update->id -1]->value_type, - data->signal_handlers[update->id], - unpacked); + const gchar *name = data->properties[update->id -1]->name; + g_debug ("Unpacking '%s' with ID %u\n", name, update->id); + + if (update->scalar == TRUE) { + PropUpdateScalar *scalar_update = (PropUpdateScalar *)update; + GValue tmp = G_VALUE_INIT; + g_value_init (&tmp, data->properties[update->id -1]->value_type); + g_value_set_from_raw_data (&tmp, &scalar_update->prop_raw); + g_object_set_property (G_OBJECT (data->cam), name, &tmp); + } + + g_signal_handler_unblock (data->cam, data->signal_handlers[update->id]); + g_debug ("Done."); + } + + if (request->message->msg == KIROCS_FETCH) { + gchar* property_name = (gchar *)request->message->payload; + + KiroRequest *request = g_malloc0 (sizeof (KiroRequest)); + request->peer_rank = data->peer_rank; + request->callback = send_clear_callback; + request->user_data = NULL; + request->message = g_malloc0 (sizeof (KiroMessage)); - g_free (unpacked); + request->message->msg = KIROCS_UPDATE; + request->message->size = sizeof (PropUpdateScalar); + request->message->payload = g_malloc0 (request->message->size); + PropUpdateScalar *update = (PropUpdateScalar *)request->message->payload; + g_object_get (data->cam, property_name, &update->prop_raw, NULL); + + update->base.id = property_id_from_name (property_name, data->n_properties, data->properties); + update->base.size = 1; + update->base.scalar = TRUE; + + GError *error = NULL; + if (!kiro_messenger_send (data->messenger, request, &error)) { + g_error ("Oh shit! '%s'", error->message); + g_error_free (error); + //TODO + //Things + } } - status->request_cleanup = TRUE; + if (request->message->payload) + g_free (request->message->payload); + g_free (request->message); - return KIRO_CALLBACK_CONTINUE; + kiro_messenger_receive (data->messenger, request); } @@ -316,46 +348,79 @@ over an InfiniBand network and control the loaded remote camera as if it was con // wait for the first peer while (data.peer_rank == 0) {}; - guint num_properties = 0; + + KiroMessage message; data.signal_handlers = NULL; - data.properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (data.cam), &num_properties); + data.properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (data.cam), &data.n_properties); if (!(*data.properties)) { g_object_unref (data.messenger); g_object_unref (data.cam); g_error ("No properties exposed by camera '%s'.", camera_name); } else { - data.signal_handlers = g_malloc0 (sizeof (gulong) * (num_properties + 1)); //0 is not a valid property ID + data.signal_handlers = g_malloc0 (sizeof (gulong) * (data.n_properties + 1)); //0 is not a valid property ID - for (guint idx=0; idx < num_properties; idx++) { + for (guint idx=0; idx < data.n_properties; idx++) { - gint prop_id = property_id_from_name (data.properties[idx]->name); - if (0 >= prop_id) { + if (idx >= N_BASE_PROPERTIES - 1) { //NONE Base Property. //Inform peer and setup - continue; + g_debug ("Asking peer to install property '%s' with ID %u", data.properties[idx]->name, idx + 1); + message.msg = KIROCS_INSTALL; + message.size = sizeof (PropertyRequisition) + strlen (data.properties[idx]->name); + message.payload = g_malloc0 (message.size); + + PropertyRequisition *req = message.payload; + req->id = idx + 1; + req->value_type = data.properties[idx]->value_type; + + switch (req->value_type) { + case G_TYPE_BOOLEAN: + req->spec.bool_spec = *(GParamSpecBoolean *)data.properties[idx]; + break; + default: + g_debug ("FOOBAR"); + } + strcpy (req->name, data.properties[idx]->name); + + if (!kiro_messenger_send_blocking (data.messenger, &message, data.peer_rank, &error)) { + g_error ("Oh shit!"); + //TODO + //Things + } + g_free (req); } + else + peer_inform_update (data.cam, data.properties[idx], &data); - data.signal_handlers[prop_id] = setup_signal_handler (data.cam, data.properties[idx], &data); + guint handler_id = setup_signal_handler (data.cam, data.properties[idx], &data); + data.signal_handlers[idx + 1] = handler_id; + g_debug ("Setup handler for property '%s' with handler ID %u", data.properties[idx]->name, handler_id); } } //All done. Send READY - KiroMessage message; - message.peer_rank = data.peer_rank; message.msg = KIROCS_READY; message.size = 0; message.payload = NULL; - if (!kiro_messenger_send_blocking (data.messenger, &message, &error)) { + if (!kiro_messenger_send_blocking (data.messenger, &message, data.peer_rank, &error)) { g_error ("Oh shit!"); //TODO //Things } + KiroRequest request; + request.id = 0; + request.callback = (KiroMessageCallbackFunc) receive_callback; + request.user_data = (gpointer) &data; - kiro_messenger_add_receive_callback (data.messenger, (KiroMessageCallbackFunc)receive_callback, &data); - while (!(data.exit_flag)) {}; + kiro_messenger_receive (data.messenger, &request); + while (!(data.exit_flag)) { + sleep (5); + //TODO + //Check if connection is still alive, and if not, reinitialize + }; g_free (data.properties); diff --git a/src/uca-kiro-camera.c b/src/uca-kiro-camera.c index 3483f9d..f8938fa 100644 --- a/src/uca-kiro-camera.c +++ b/src/uca-kiro-camera.c @@ -59,6 +59,17 @@ static const gint kiro_overrideables[] = { static GParamSpec *kiro_properties[N_PROPERTIES] = { NULL, }; +//+1 to make index and property ID identical +static guint64 kiro_scalar_prop_buffers[N_PROPERTIES] = { 0, }; + +typedef struct { + GParamSpec *pspec; + guint32 remote_id; + guint32 local_id; + guint64 buffer; +} KiroDynamicScalarProperty; + + struct _UcaKiroCameraPrivate { guint8 *dummy_data; guint current_frame; @@ -66,7 +77,8 @@ struct _UcaKiroCameraPrivate { gchar *kiro_address; gchar *kiro_port; gchar *remote_name; - GParamSpec **kiro_dynamic_attributes; + GList *property_install_list; + KiroDynamicScalarProperty *kiro_dynamic_scalar_properties; gboolean thread_running; gboolean kiro_connected; @@ -75,12 +87,14 @@ struct _UcaKiroCameraPrivate { GThread *grab_thread; KiroMessenger *messenger; gulong peer_rank; + KiroRequest *rec_request; guint roi_height; guint roi_width; guint bytes_per_pixel; }; + static gpointer kiro_grab_func(gpointer data) { @@ -223,7 +237,7 @@ uca_kiro_camera_grab (UcaCamera *camera, gpointer data, GError **error) /* 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. */ + /* //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); */ @@ -270,22 +284,69 @@ kiro_address_decode (const gchar *addr_in, gchar **addr, gchar **port, GError ** } -static KiroContinueFlag -receive_handler (KiroMessageStatus *status, gpointer user_data) +static void +null_callback (gpointer unused) +{ + (void)unused; +} + + + + +void +receive_handler (KiroRequest *request, gpointer user_data) { UcaKiroCamera *cam = (UcaKiroCamera *)user_data; UcaKiroCameraPrivate *priv = UCA_KIRO_CAMERA_GET_PRIVATE (cam); - - KiroMessage *msg = status->message; + + KiroMessage *msg = request->message; + + if (msg->msg == KIROCS_INSTALL) { + PropertyRequisition *req = (PropertyRequisition *)msg->payload; + g_debug ("Got requisition for a non-base property '%s' of type '%s' with ID %u", req->name, g_type_name (req->value_type), + req->id); + priv->property_install_list = g_list_append (priv->property_install_list, msg->payload); + msg->payload = NULL; + goto done; + } if (msg->msg == KIROCS_READY) { g_debug ("Interface Setup Done."); priv->kiro_connected = TRUE; - return KIRO_CALLBACK_CONTINUE; + goto done; + } + + if (msg->msg == KIROCS_UPDATE) { + PropUpdate *update = (PropUpdate *)request->message->payload; + const gchar *name = NULL; + gpointer buffer = NULL; + + if (update->scalar == TRUE) { + PropUpdateScalar *scalar_update = (PropUpdateScalar *)request->message->payload; + + if (update->id >= N_BASE_PROPERTIES) { + name = priv->kiro_dynamic_scalar_properties[update->id - N_BASE_PROPERTIES].pspec->name; + buffer = &priv->kiro_dynamic_scalar_properties[update->id - N_BASE_PROPERTIES].buffer; + } + else { + name = uca_camera_props[update->id]; + buffer = &kiro_scalar_prop_buffers[update->id]; + } + + memcpy (buffer, &scalar_update->prop_raw, sizeof (guint64)); + } + + g_debug ("Peer informed us about an update of property '%s' (ID: %u)", name, update->id); + goto done; } g_message ("Message Type '%u' is unhandled.", msg->msg); - return KIRO_CALLBACK_CONTINUE; + +done: + if (msg->payload) + g_free (msg->payload); + g_free (msg); + kiro_messenger_receive (priv->messenger, request); } @@ -301,21 +362,63 @@ uca_kiro_camera_clone_interface(UcaKiroCamera *kiro_camera) priv->messenger = kiro_messenger_new (); } - priv->kiro_connected = FALSE; + priv->rec_request = g_malloc0 (sizeof (KiroRequest)); + priv->rec_request->id = 0; + priv->rec_request->callback = (KiroMessageCallbackFunc) receive_handler; + priv->rec_request->user_data = (gpointer) kiro_camera; + kiro_messenger_receive (priv->messenger, priv->rec_request); - kiro_messenger_add_receive_callback (priv->messenger, receive_handler, kiro_camera); + priv->kiro_connected = FALSE; kiro_messenger_connect (priv->messenger, priv->kiro_address, priv->kiro_port, &priv->peer_rank, &initable_iface_error); if (initable_iface_error) { priv->construction_error = TRUE; - kiro_messenger_remove_receive_callback (priv->messenger); + g_free (priv->rec_request); return; } //Wait until the remote side has given us the "READY" signal - while (!priv->kiro_connected) {}; + while (!priv->kiro_connected) {}; + + guint count = g_list_length (priv->property_install_list); + if (count > 0) { + g_debug ("Registering buffers for %u dyanmic properties", count); + priv->kiro_dynamic_scalar_properties = g_malloc0 (count * sizeof (KiroDynamicScalarProperty)); + GList *curr = g_list_first (priv->property_install_list); + guint idx = 0; + while (curr) { + PropertyRequisition *req = (PropertyRequisition *)curr->data; + g_debug ("Registering dynamic property '%s'", req->name); + GParamSpec *pspec = g_param_spec_boolean (req->name, "Remote Property", + "Remote Property", TRUE, G_PARAM_READWRITE); + guint local_id = N_PROPERTIES + idx; + g_object_class_install_property (gobject_class, local_id, pspec); + + priv->kiro_dynamic_scalar_properties[idx].local_id = local_id; + priv->kiro_dynamic_scalar_properties[idx].remote_id = req->id; + priv->kiro_dynamic_scalar_properties[idx].pspec = pspec; + + KiroMessage message; + message.msg = KIROCS_FETCH; + message.size = strlen (req->name) + 1; //Don't forget the NULL-byte + message.payload = &(req->name); + + g_debug ("Sending request to fetch value of property '%s'", req->name); + GError *error = NULL; + kiro_messenger_send_blocking (priv->messenger, &message, priv->peer_rank, &error); + if (error) { + g_error ("Oh shit! (%s)", error->message); + g_error_free (error); + } + + idx++; + curr = g_list_next (curr); + } + g_list_free (priv->property_install_list); + } + + if (priv->construction_error) { - //something went wrong. Tear down the connection. kiro_messenger_stop (priv->messenger); //TODO @@ -337,7 +440,7 @@ uca_kiro_camera_set_property(GObject *object, guint property_id, const GValue *v priv->kiro_address_string = g_value_dup_string (value); break; default: - g_debug ("Updating %s.", pspec->name); + g_debug ("Updating %s.", pspec->name); if (!priv->kiro_connected) { g_warning ("Trying to modify a property before a connection to the remote camera was established."); @@ -345,31 +448,40 @@ uca_kiro_camera_set_property(GObject *object, guint property_id, const GValue *v return; } - GError *error = NULL; - - GVariant *tmp = variant_from_scalar (value); - gsize data_size = g_variant_get_size (tmp); - - PropUpdate *test = g_malloc0 (sizeof (PropUpdate) + data_size); - test->id = property_id_from_name (pspec->name); - test->type[0] = gtype_to_gvariant_class (pspec->value_type); - test->size = data_size; - g_variant_store (tmp, test->val); - g_variant_unref (tmp); + if (property_id >= N_PROPERTIES) { + g_debug ("Non-Base-Property ID %u (Index: %u)", property_id, property_id - N_PROPERTIES); + g_value_write_to_raw_data (value, &(priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].buffer)); + } + else + g_value_write_to_raw_data (value, &kiro_scalar_prop_buffers[property_id]); KiroMessage message; - message.peer_rank = priv->peer_rank; message.msg = KIROCS_UPDATE; - message.payload = test; - message.size = sizeof (PropUpdate) + data_size; + message.size = sizeof (PropUpdate) + sizeof (guint64); + message.payload = g_malloc0 (message.size); + gpointer data_pointer = message.payload + sizeof (PropUpdate); - kiro_messenger_send_blocking (priv->messenger, &message, &error); + PropUpdate *update = (PropUpdate *)message.payload; + update->size = 1; + update->scalar = TRUE; + + if (property_id > N_BASE_PROPERTIES) { + update->id = priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].remote_id; + memcpy (data_pointer, &(priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].buffer), sizeof (guint64)); + } + else { + update->id = property_id; + memcpy (data_pointer, &kiro_scalar_prop_buffers[property_id], sizeof (guint64)); + } + + + GError *error = NULL; + kiro_messenger_send_blocking (priv->messenger, &message, priv->peer_rank, &error); if (error) { - g_free (test); g_error ("Oh shit! (%s)", error->message); + g_error_free (error); } - - g_free (test); + g_free (message.payload); } } @@ -390,7 +502,14 @@ uca_kiro_camera_get_property(GObject *object, guint property_id, GValue *value, g_value_set_string (value, priv->remote_name); break; default: - //try_handle_read_tango_property (object, property_id, value, pspec); + //TODO: + //Handle non-scalar types specifically + if (property_id <= N_BASE_PROPERTIES) { + g_value_set_from_raw_data (value, &kiro_scalar_prop_buffers[property_id]); + } + else { + g_value_set_from_raw_data (value, &(priv->kiro_dynamic_scalar_properties[property_id - N_PROPERTIES].buffer)); + } break; } } @@ -429,13 +548,13 @@ ufo_kiro_camera_initable_init (GInitable *initable, 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; } @@ -448,16 +567,16 @@ uca_kiro_initable_iface_init (GInitableIface *iface) static void uca_kiro_camera_constructed (GObject *object) { - //Initialization for the KIRO Server and TANGO Interface cloning is moved + //Initialization for the KIRO Messenger and 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); priv->construction_error = FALSE; - + GValue address = G_VALUE_INIT; g_value_init(&address, G_TYPE_STRING); uca_kiro_camera_get_property (object, PROP_KIRO_ADDRESS, &address, NULL); @@ -502,7 +621,7 @@ uca_kiro_camera_class_init(UcaKiroCameraClass *klass) for (guint i = 0; i < N_BASE_PROPERTIES; i++) g_object_class_override_property (gobject_class, i, uca_camera_props[i]); - + kiro_properties[PROP_KIRO_ADDRESS] = g_param_spec_string("kiro-address", "KIRO Server Address", @@ -512,8 +631,8 @@ uca_kiro_camera_class_init(UcaKiroCameraClass *klass) 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", + "Name of the remote camera", + "Name of the camera plugin that is loaded on the KIRO remote side", "NONE", G_PARAM_READABLE); @@ -530,11 +649,9 @@ uca_kiro_camera_init(UcaKiroCamera *self) self->priv->grab_thread = NULL; self->priv->current_frame = 0; self->priv->kiro_address_string = g_strdup ("NONE"); - self->priv->kiro_address = g_strdup ("NONE"); - self->priv->kiro_port = g_strdup ("NONE"); self->priv->remote_name = g_strdup ("NONE"); self->priv->construction_error = FALSE; - self->priv->kiro_dynamic_attributes = NULL; + self->priv->kiro_dynamic_scalar_properties = NULL; self->priv->messenger = kiro_messenger_new (); self->priv->peer_rank = 0; diff --git a/src/uca-kiro-camera.h b/src/uca-kiro-camera.h index a84e574..48c7017 100644 --- a/src/uca-kiro-camera.h +++ b/src/uca-kiro-camera.h @@ -76,28 +76,43 @@ G_END_DECLS //HELPER FUNCTIONS AND CONSTRUCTS FOR SERVER AND CAMERA PLUGIN typedef enum { KIROCS_UPDATE, + KIROCS_FETCH, KIROCS_INSTALL, KIROCS_READY, KIROCS_RPC, KIROCS_EXIT -}KiroCsCommands; +} KiroCsCommands; + +typedef enum { + KIROCS_RPC_START_RECORDING, + KIROCS_RPC_STOP_RECORDING, + KIROCS_RPC_START_READOUT, + KIROCS_RPC_STOP_READOUT, + KIROCS_RPC_TRIGGER, + KIROCS_RPC_GRAB, + KIROCS_RPC_READOUT +// KIROCS_RPC_WRITE is currently not supported +} KiroCsRPC; typedef struct { guint32 id; guint32 size; gboolean scalar; - gchar type[2]; - gchar val[1]; } PropUpdate; typedef struct { - guint32 str_len; + PropUpdate base; + guint64 prop_raw; +} PropUpdateScalar; + +typedef struct { + PropUpdate base; gchar str[1]; -}StrProp; +} PropUpdateString; typedef struct { + guint32 id; GType value_type; - guint32 name_len; union PSpecs { GParamSpecBoolean bool_spec; GParamSpecChar char_spec; @@ -109,7 +124,6 @@ typedef struct { GParamSpecUInt64 uint64_spec; GParamSpecFloat float_spec; GParamSpecDouble double_spec; - StrProp str_spec; } spec; gchar name[1]; } PropertyRequisition; @@ -381,18 +395,136 @@ variant_from_scalar (GValue *value) } -gint -property_id_from_name(const gchar* name) +guint +property_id_from_name(const gchar* name, guint n_props, GParamSpec **props) { - gint idx = 0; + guint idx = 0; gboolean found = FALSE; - for (;idx < N_BASE_PROPERTIES; ++idx) { - if (0 == g_strcmp0(name, uca_camera_props[idx])) { + for (;idx < n_props; ++idx) { + if (0 == g_strcmp0(name, props[idx]->name)) { found = TRUE; break; } } - return found ? idx : -1; + return found ? (idx + 1) : 0; } + +void +g_value_write_to_raw_data (const GValue *value, gpointer raw) +{ + GType type = G_VALUE_TYPE (value); + + switch (type) { + case G_TYPE_BOOLEAN: + *(gboolean *)raw = g_value_get_boolean (value); + break; + case G_TYPE_CHAR: + *(gchar *)raw = g_value_get_char (value); + break; + case G_TYPE_INT: + *(gint *)raw = g_value_get_int (value); + break; + case G_TYPE_ENUM: + *(gint *)raw = g_value_get_enum (value); + break; + case G_TYPE_UINT: + *(guint *)raw = g_value_get_uint (value); + break; + case G_TYPE_LONG: + *(glong *)raw = g_value_get_long (value); + break; + case G_TYPE_ULONG: + *(gulong *)raw = g_value_get_ulong (value); + break; + case G_TYPE_INT64: + *(gint64 *)raw = g_value_get_int64 (value); + break; + case G_TYPE_UINT64: + *(guint64 *)raw = g_value_get_uint64 (value); + break; + case G_TYPE_FLOAT: + *(gfloat *)raw = g_value_get_float (value); + break; + case G_TYPE_DOUBLE: + *(gdouble *)raw = g_value_get_double (value); + 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) { + *(gint *)raw = g_value_get_int (value); + break; + } + + if (type == UCA_TYPE_CAMERA_TRIGGER_TYPE) { + *(gint *)raw = g_value_get_int (value); + break; + } + + g_critical ("Type %s not handled! (GET)", g_type_name (type)); + break; + } +} + + +void +g_value_set_from_raw_data (GValue *value, gpointer raw) +{ + GType type = G_VALUE_TYPE (value); + + switch (type) { + case G_TYPE_BOOLEAN: + g_value_set_boolean (value, *(gboolean *)raw); + break; + case G_TYPE_CHAR: + g_value_set_char (value, *(gchar *)raw); + break; + case G_TYPE_INT: + g_value_set_int (value, *(gint *)raw); + break; + case G_TYPE_ENUM: + g_value_set_enum (value, *(gint *)raw); + break; + case G_TYPE_UINT: + g_value_set_uint (value, *(guint *)raw); + break; + case G_TYPE_LONG: + g_value_set_long (value, *(glong *)raw); + break; + case G_TYPE_ULONG: + g_value_set_ulong (value, *(gulong *)raw); + break; + case G_TYPE_INT64: + g_value_set_int64 (value, *(gint64 *)raw); + break; + case G_TYPE_UINT64: + g_value_set_uint64 (value, *(guint64 *)raw); + break; + case G_TYPE_FLOAT: + g_value_set_float (value, *(gfloat *)raw); + break; + case G_TYPE_DOUBLE: + g_value_set_double (value, *(gdouble *)raw); + 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) { + g_value_set_enum (value, *(gint *)raw); + break; + } + + if (type == UCA_TYPE_CAMERA_TRIGGER_TYPE) { + g_value_set_enum (value, *(gint *)raw); + break; + } + + g_critical ("Type %s not handled! (SET)", g_type_name (type)); + break; + } +} + + + #endif -- cgit v1.2.1