Browse Source

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
Timo Dritschler 8 years ago
parent
commit
786627dcef
4 changed files with 442 additions and 128 deletions
  1. 2 2
      bin/CMakeLists.txt
  2. 134 69
      bin/kiro-camera-server.c
  3. 161 44
      src/uca-kiro-camera.c
  4. 145 13
      src/uca-kiro-camera.h

+ 2 - 2
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})

+ 134 - 69
bin/kiro-camera-server.c

@@ -19,6 +19,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #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);

+ 161 - 44
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;

+ 145 - 13
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