[aravis/chunk: 5/6] chunk_parser: implementation completion



commit a8da2c7962fac6094627fe4b2985b43e7a050971
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Mon Aug 18 18:26:07 2014 +0200

    chunk_parser: implementation completion

 docs/reference/aravis/aravis-docs.xml     |    1 +
 docs/reference/aravis/aravis-sections.txt |   36 +++++++
 src/arvchunkparser.c                      |   75 ++++++++++++--
 src/arvchunkparser.h                      |   27 ++++-
 src/arvdebug.c                            |    6 +
 src/arvdebug.h                            |    5 +
 src/arvdevice.c                           |   24 ++++
 src/arvdevice.h                           |    3 +
 src/arvgc.c                               |   70 +++++++++++--
 src/arvgc.h                               |    6 +-
 src/arvgcport.c                           |  163 +++++++++++++++++++++++------
 src/arvgcport.h                           |    3 +
 src/arvgcpropertynode.c                   |    8 ++
 src/arvgcpropertynode.h                   |    2 +
 14 files changed, 375 insertions(+), 54 deletions(-)
---
diff --git a/docs/reference/aravis/aravis-docs.xml b/docs/reference/aravis/aravis-docs.xml
index b2d6ae5..58b44cb 100644
--- a/docs/reference/aravis/aravis-docs.xml
+++ b/docs/reference/aravis/aravis-docs.xml
@@ -43,6 +43,7 @@
                        <xi:include href="xml/arvdevice.xml"/>
                        <xi:include href="xml/arvstream.xml"/>
                        <xi:include href="xml/arvbuffer.xml"/>
+                       <xi:include href="xml/arvchunkparser.xml"/>
                </chapter>
 
                <chapter>
diff --git a/docs/reference/aravis/aravis-sections.txt b/docs/reference/aravis/aravis-sections.txt
index a335008..ed42b68 100644
--- a/docs/reference/aravis/aravis-sections.txt
+++ b/docs/reference/aravis/aravis-sections.txt
@@ -79,6 +79,7 @@ arv_buffer_new
 arv_buffer_new_full
 arv_buffer_new_allocate
 arv_buffer_get_data
+arv_buffer_get_chunk_data
 ARV_PIXEL_FORMAT_BIT_PER_PIXEL
 ARV_PIXEL_FORMAT_BAYER_BG_10
 ARV_PIXEL_FORMAT_BAYER_BG_12
@@ -216,6 +217,7 @@ ARV_GC_PORT_CLASS
 ARV_IS_GC_PORT_CLASS
 ARV_GC_PORT_GET_CLASS
 <SUBSECTION Private>
+ArvGcPortPrivate
 ArvGcPortClass
 </SECTION>
 
@@ -227,6 +229,7 @@ ArvDevice
 ArvDeviceStatus
 arv_device_error_quark
 arv_device_create_stream
+arv_device_create_chunk_parser
 arv_device_read_memory
 arv_device_write_memory
 arv_device_read_register
@@ -262,6 +265,29 @@ ARV_DEVICE_NAME_REPLACEMENT_CHARACTER
 </SECTION>
 
 <SECTION>
+<FILE>arvchunkparser</FILE>
+<TITLE>ArvChunkParser</TITLE>
+ArvChunkParserStatus
+arv_chunk_parser_get_float_value
+arv_chunk_parser_get_integer_value
+arv_chunk_parser_get_string_value
+arv_chunk_parser_new
+<SUBSECTION Standard>
+ArvChunkParser
+arv_chunk_parser_get_type
+ARV_CHUNK_PARSER
+ARV_CHUNK_PARSER_CLASS
+ARV_CHUNK_PARSER_GET_CLASS
+ARV_IS_CHUNK_PARSER
+ARV_IS_CHUNK_PARSER_CLASS
+ARV_TYPE_CHUNK_PARSER
+<SUBSECTION Private>
+ArvChunkParserPrivate
+ARV_CHUNK_PARSER_ERROR
+arv_chunk_parser_error_quark
+</SECTION>
+
+<SECTION>
 <FILE>arvgcnode</FILE>
 <TITLE>ArvGcNode</TITLE>
 ArvGcNode
@@ -304,6 +330,7 @@ arv_gc_property_node_new_minimum
 arv_gc_property_node_new_msb
 arv_gc_property_node_new_off_value
 arv_gc_property_node_new_on_value
+arv_gc_property_node_new_chunk_id
 arv_gc_property_node_new_p_address
 arv_gc_property_node_new_p_command_value
 arv_gc_property_node_new_p_feature
@@ -631,6 +658,8 @@ ArvGc
 arv_gc_new
 arv_gc_get_node
 arv_gc_get_device
+arv_gc_get_buffer
+arv_gc_set_buffer
 <SUBSECTION Standard>
 ARV_GC
 ARV_IS_GC
@@ -640,6 +669,7 @@ ARV_GC_CLASS
 ARV_IS_GC_CLASS
 ARV_GC_GET_CLASS
 <SUBSECTION Private>
+ArvGcPrivate
 ArvGcClass
 ArvGcNameSpace
 ArvGcAccessMode
@@ -1434,11 +1464,16 @@ arv_warning_misc
 arv_warning_stream
 arv_warning_stream_thread
 arv_g_string_append_hex_dump
+arv_debug_category_chunk
+arv_debug_chunk
+arv_log_chunk
+arv_warning_chunk
 </SECTION>
 
 <SECTION>
 <FILE>arvgvsp</FILE>
 <TITLE>ArvGvsp</TITLE>
+ArvGvspPayloadType
 ArvGvspPacketType
 ArvGvspContentType
 ArvGvspDataLeader
@@ -1452,6 +1487,7 @@ arv_gvsp_packet_get_height
 arv_gvsp_packet_get_packet_id
 arv_gvsp_packet_get_packet_type
 arv_gvsp_packet_get_content_type
+arv_gvsp_packet_get_payload_type
 arv_gvsp_packet_get_pixel_format
 arv_gvsp_packet_get_timestamp
 arv_gvsp_packet_get_width
diff --git a/src/arvchunkparser.c b/src/arvchunkparser.c
index 64994f4..719ca52 100644
--- a/src/arvchunkparser.c
+++ b/src/arvchunkparser.c
@@ -29,6 +29,11 @@
  */
 
 #include <arvchunkparser.h>
+#include <arvbuffer.h>
+#include <arvgcinteger.h>
+#include <arvgcfloat.h>
+#include <arvgcstring.h>
+#include <arvdebug.h>
 
 enum {
        ARV_CHUNK_PARSER_PROPERTY_0,
@@ -38,31 +43,80 @@ enum {
 
 static GObjectClass *parent_class = NULL;
 
+GQuark
+arv_chunk_parser_error_quark (void)
+{
+       return g_quark_from_static_string ("arv-chunk-parser-error-quark");
+}
+
 struct _ArvChunkParserPrivate {
        ArvGc *genicam;
 };
 
 const char *
-arv_chunk_parser_get_string_feature_value (ArvChunkParser *parser, ArvBuffer *buffer, const char *feature)
+arv_chunk_parser_get_string_value (ArvChunkParser *parser, ArvBuffer *buffer, const char *chunk)
 {
-       return NULL;
+       ArvGcNode *node;
+       const char *string = NULL;
+
+       g_return_val_if_fail (ARV_IS_CHUNK_PARSER (parser), NULL);
+       g_return_val_if_fail (ARV_IS_BUFFER (buffer), NULL);
+
+       node = arv_gc_get_node (parser->priv->genicam, chunk);
+       arv_gc_set_buffer (parser->priv->genicam, buffer);
+
+       if (ARV_IS_GC_STRING (node))
+               string = arv_gc_string_get_value (ARV_GC_STRING (node), NULL);
+       else
+               arv_warning_device ("[ArvChunkParser::get_string_value] Node '%s' is not a string", chunk);
+
+       return string;
 }
 
 gint64
-arv_chunk_parser_get_integer_feature_value (ArvChunkParser *parser, ArvBuffer *buffer, const char *feature)
+arv_chunk_parser_get_integer_value (ArvChunkParser *parser, ArvBuffer *buffer, const char *chunk)
 {
-       return 0;
+       ArvGcNode *node;
+       gint64 value = 0;
+
+       g_return_val_if_fail (ARV_IS_CHUNK_PARSER (parser), 0.0);
+       g_return_val_if_fail (ARV_IS_BUFFER (buffer), 0.0);
+
+       node = arv_gc_get_node (parser->priv->genicam, chunk);
+       arv_gc_set_buffer (parser->priv->genicam, buffer);
+
+       if (ARV_IS_GC_INTEGER (node))
+               value = arv_gc_integer_get_value (ARV_GC_INTEGER (node), NULL);
+       else
+               arv_warning_device ("[ArvChunkParser::get_integer_value] Node '%s' is not an integer", chunk);
+
+       return value;
 }
 
 double
-arv_chunk_parser_get_float_feature_value (ArvChunkParser *parser, ArvBuffer *buffer, const char *feature)
+arv_chunk_parser_get_float_value (ArvChunkParser *parser, ArvBuffer *buffer, const char *chunk)
 {
-       return 0.0;
+       ArvGcNode *node;
+       double value = 0.0;
+
+       g_return_val_if_fail (ARV_IS_CHUNK_PARSER (parser), 0.0);
+       g_return_val_if_fail (ARV_IS_BUFFER (buffer), 0.0);
+
+       node = arv_gc_get_node (parser->priv->genicam, chunk);
+       arv_gc_set_buffer (parser->priv->genicam, buffer);
+
+       if (ARV_IS_GC_FLOAT (node))
+               value = arv_gc_float_get_value (ARV_GC_FLOAT (node), NULL);
+       else 
+               arv_warning_chunk ("[ArvChunkParser::get_float_value] Node '%s' is not a float", chunk);
+
+       return value;
 }
 
 /**
  * arv_chunk_parser_new:
- * @genicam: a #ArvGc
+ * @xml: XML genicam data
+ * @size: data size, -1 if NULL terminated
  *
  * Creates a new chunk_parser.
  *
@@ -72,14 +126,19 @@ arv_chunk_parser_get_float_feature_value (ArvChunkParser *parser, ArvBuffer *buf
  */
 
 ArvChunkParser *
-arv_chunk_parser_new (ArvGc *genicam)
+arv_chunk_parser_new (const char *xml, gsize size)
 {
        ArvChunkParser *chunk_parser;
+       ArvGc *genicam;
+
+       genicam = arv_gc_new (NULL, xml, size);
 
        g_return_val_if_fail (ARV_IS_GC (genicam), NULL);
 
        chunk_parser = g_object_new (ARV_TYPE_CHUNK_PARSER, "genicam", genicam, NULL);
 
+       g_object_unref (genicam);
+
        return chunk_parser;
 }
 
diff --git a/src/arvchunkparser.h b/src/arvchunkparser.h
index 161b1c6..801eadc 100644
--- a/src/arvchunkparser.h
+++ b/src/arvchunkparser.h
@@ -28,6 +28,23 @@
 
 G_BEGIN_DECLS
 
+#define ARV_CHUNK_PARSER_ERROR arv_chunk_parser_error_quark()
+
+/**
+ * ArvChunkParserStatus:
+ * @ARV_CHUNK_PARSER_STATUS_UNKNOWN: unknown status
+ * @ARV_CHUNK_PARSER_STATUS_SUCCESS: no error has occured
+ * @ARV_CHUNK_PARSER_STATUS_BUFFER_NOT_FOUND: buffer not found
+ * @ARV_CHUNK_PARSER_STATUS_CHUNK_NOT_FOUND: chunk not found
+ */
+
+typedef enum {
+       ARV_CHUNK_PARSER_STATUS_UNKNOWN = -1,
+       ARV_CHUNK_PARSER_STATUS_SUCCESS =  0,
+       ARV_CHUNK_PARSER_STATUS_BUFFER_NOT_FOUND,
+       ARV_CHUNK_PARSER_STATUS_CHUNK_NOT_FOUND
+} ArvChunkParserStatus;
+
 #define ARV_TYPE_CHUNK_PARSER             (arv_chunk_parser_get_type ())
 #define ARV_CHUNK_PARSER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), ARV_TYPE_CHUNK_PARSER, 
ArvChunkParser))
 #define ARV_CHUNK_PARSER_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), ARV_TYPE_CHUNK_PARSER, 
ArvChunkParserClass))
@@ -50,10 +67,12 @@ struct _ArvChunkParserClass {
 
 GType arv_chunk_parser_get_type (void);
 
-ArvChunkParser *       arv_chunk_parser_new                            (ArvGc *genicam);
-const char *           arv_chunk_parser_get_string_feature_value       (ArvChunkParser *parser, ArvBuffer 
*buffer, const char *feature);
-gint64                 arv_chunk_parser_get_integer_feature_value      (ArvChunkParser *parser, ArvBuffer 
*buffer, const char *feature); 
-double                 arv_chunk_parser_get_float_feature_value        (ArvChunkParser *parser, ArvBuffer 
*buffer, const char *feature);
+GQuark                         arv_chunk_parser_error_quark            (void);
+
+ArvChunkParser *       arv_chunk_parser_new                    (const char *xml, gsize size);
+const char *           arv_chunk_parser_get_string_value       (ArvChunkParser *parser, ArvBuffer *buffer, 
const char *chunk);
+gint64                 arv_chunk_parser_get_integer_value      (ArvChunkParser *parser, ArvBuffer *buffer, 
const char *chunk); 
+double                 arv_chunk_parser_get_float_value        (ArvChunkParser *parser, ArvBuffer *buffer, 
const char *chunk);
 
 G_END_DECLS
 
diff --git a/src/arvdebug.c b/src/arvdebug.c
index 57b8109..0c51178 100644
--- a/src/arvdebug.c
+++ b/src/arvdebug.c
@@ -41,6 +41,12 @@ ArvDebugCategory arv_debug_category_device =
        .level = -1
 };
 
+ArvDebugCategory arv_debug_category_chunk =
+{
+       .name = "chunk",
+       .level = -1
+};
+
 ArvDebugCategory arv_debug_category_stream =
 {
        .name = "stream",
diff --git a/src/arvdebug.h b/src/arvdebug.h
index b23ebcf..81a1fe4 100644
--- a/src/arvdebug.h
+++ b/src/arvdebug.h
@@ -43,6 +43,7 @@ typedef struct {
 extern ArvDebugCategory arv_debug_category_dom;
 extern ArvDebugCategory arv_debug_category_interface;
 extern ArvDebugCategory arv_debug_category_device;
+extern ArvDebugCategory arv_debug_category_chunk;
 extern ArvDebugCategory arv_debug_category_stream;
 extern ArvDebugCategory arv_debug_category_stream_thread;
 extern ArvDebugCategory arv_debug_category_gvcp;
@@ -63,6 +64,10 @@ extern ArvDebugCategory arv_debug_category_misc;
 #define arv_log_device(...)            arv_log (&arv_debug_category_device, __VA_ARGS__)
 #define arv_warning_device(...)                arv_warning (&arv_debug_category_device, __VA_ARGS__)
 
+#define arv_debug_chunk(...)           arv_debug (&arv_debug_category_chunk, __VA_ARGS__)
+#define arv_log_chunk(...)             arv_log (&arv_debug_category_chunk, __VA_ARGS__)
+#define arv_warning_chunk(...)         arv_warning (&arv_debug_category_chunk, __VA_ARGS__)
+
 #define arv_debug_stream(...)          arv_debug (&arv_debug_category_stream, __VA_ARGS__)
 #define arv_log_stream(...)            arv_log (&arv_debug_category_stream, __VA_ARGS__)
 #define arv_warning_stream(...)                arv_warning (&arv_debug_category_stream, __VA_ARGS__)
diff --git a/src/arvdevice.c b/src/arvdevice.c
index 99a6245..94b0838 100644
--- a/src/arvdevice.c
+++ b/src/arvdevice.c
@@ -225,6 +225,30 @@ arv_device_get_genicam_xml (ArvDevice *device, size_t *size)
 }
 
 /**
+ * arv_device_create_chunk_parser:
+ * @device: a #ArvDevice
+ *
+ * Create a #ArvChunkParser object, to be used for chunk data extraction from #ArvBuffer.
+ *
+ * Returns: (transfer full): a new #ArvChunkParser object, NULL on error.
+ *
+ * Since: 0.4.0
+ **/
+
+ArvChunkParser *
+arv_device_create_chunk_parser (ArvDevice *device)
+{
+       const char *xml = NULL;
+       gsize size = 0;
+
+       g_return_val_if_fail (ARV_IS_DEVICE (device), NULL);
+
+       xml = arv_device_get_genicam_xml (device, &size);
+
+       return arv_chunk_parser_new (xml, size);
+}
+
+/**
  * arv_device_get_feature:
  * @device: a #ArvDevice
  * @feature: feature name
diff --git a/src/arvdevice.h b/src/arvdevice.h
index 185cbe2..941cde9 100644
--- a/src/arvdevice.h
+++ b/src/arvdevice.h
@@ -25,6 +25,7 @@
 
 #include <arvtypes.h>
 #include <arvstream.h>
+#include <arvchunkparser.h>
 
 G_BEGIN_DECLS
 
@@ -96,6 +97,8 @@ void          arv_device_emit_control_lost_signal     (ArvDevice *device);
 
 ArvGcNode *    arv_device_get_feature                  (ArvDevice *device, const char *feature);
 
+ArvChunkParser *arv_device_create_chunk_parser         (ArvDevice *device);
+
 /* This functions may change the device status */
 
 void           arv_device_execute_command              (ArvDevice *device, const char *feature);
diff --git a/src/arvgc.c b/src/arvgc.c
index 373a714..bdd7904 100644
--- a/src/arvgc.c
+++ b/src/arvgc.c
@@ -51,12 +51,19 @@
 #include <arvgcswissknife.h>
 #include <arvgcconverter.h>
 #include <arvgcport.h>
+#include <arvbuffer.h>
 #include <arvdebug.h>
 #include <arvdomparser.h>
 #include <string.h>
 
 static GObjectClass *parent_class = NULL;
 
+struct _ArvGcPrivate {
+       GHashTable *nodes;
+       ArvDevice *device;
+       ArvBuffer *buffer;
+};
+
 /* ArvDomNode implementation */
 
 static gboolean
@@ -195,6 +202,9 @@ arv_gc_create_element (ArvDomDocument *document, const char *tag_name)
        else if (strcmp (tag_name, "pCommandValue") == 0)
                node = arv_gc_property_node_new_p_command_value ();
 
+       else if (strcmp (tag_name, "ChunkID") == 0)
+               node = arv_gc_property_node_new_chunk_id ();
+
        else if (strcmp (tag_name, "Group") == 0)
                node = arv_gc_group_node_new ();
        else
@@ -221,7 +231,7 @@ arv_gc_get_node     (ArvGc *genicam, const char *name)
        g_return_val_if_fail (ARV_IS_GC (genicam), NULL);
        g_return_val_if_fail (name != NULL, NULL);
 
-       return g_hash_table_lookup (genicam->nodes, name);
+       return g_hash_table_lookup (genicam->priv->nodes, name);
 }
 
 /**
@@ -238,7 +248,7 @@ arv_gc_get_device (ArvGc *genicam)
 {
        g_return_val_if_fail (ARV_IS_GC (genicam), NULL);
 
-       return genicam->device;
+       return genicam->priv->device;
 }
 
 void
@@ -256,8 +266,8 @@ arv_gc_register_feature_node (ArvGc *genicam, ArvGcFeatureNode *node)
 
        g_object_ref (node);
 
-       g_hash_table_remove (genicam->nodes, (char *) name);
-       g_hash_table_insert (genicam->nodes, (char *) name, node);
+       g_hash_table_remove (genicam->priv->nodes, (char *) name);
+       g_hash_table_insert (genicam->priv->nodes, (char *) name, node);
 
        arv_log_genicam ("[Gc::register_feature_node] Register node '%s' [%s]", name,
                         arv_dom_node_get_node_name (ARV_DOM_NODE (node)));
@@ -276,6 +286,45 @@ arv_gc_set_default_node_data (ArvGc *genicam, const char *node_name, const char
        arv_dom_document_append_from_memory (ARV_DOM_DOCUMENT (genicam), NULL, node_data, -1, NULL);
 }
 
+static void
+_weak_notify_cb (gpointer data, GObject *object)
+{
+       ArvGc *genicam = data;
+
+       genicam->priv->buffer = NULL;
+}
+
+void
+arv_gc_set_buffer (ArvGc *genicam, ArvBuffer *buffer)
+{
+       g_return_if_fail (ARV_IS_GC (genicam));
+       g_return_if_fail (ARV_IS_BUFFER (buffer));
+
+       if (genicam->priv->buffer != NULL)
+               g_object_weak_unref (G_OBJECT (genicam->priv->buffer), _weak_notify_cb, genicam);
+
+       g_object_weak_ref (G_OBJECT (buffer), _weak_notify_cb, genicam);
+
+       genicam->priv->buffer = buffer;
+}
+
+/**
+ * arv_gc_get_buffer:
+ * @genicam: a #ArvGc object
+ *
+ * Retrieves the binded buffer.
+ *
+ * Return value: (transfer none): a #ArvBuffer.
+ */
+
+ArvBuffer *
+arv_gc_get_buffer (ArvGc *genicam)
+{
+       g_return_val_if_fail (ARV_IS_GC (genicam), NULL);
+
+       return genicam->priv->buffer;
+}
+
 ArvGc *
 arv_gc_new (ArvDevice *device, const void *xml, size_t size)
 {
@@ -290,7 +339,7 @@ arv_gc_new (ArvDevice *device, const void *xml, size_t size)
        }
 
        genicam = ARV_GC (document);
-       genicam->device = device;
+       genicam->priv->device = device;
 
        return genicam;
 }
@@ -298,7 +347,9 @@ arv_gc_new (ArvDevice *device, const void *xml, size_t size)
 static void
 arv_gc_init (ArvGc *genicam)
 {
-       genicam->nodes = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+       genicam->priv = G_TYPE_INSTANCE_GET_PRIVATE (genicam, ARV_TYPE_GC, ArvGcPrivate);
+
+       genicam->priv->nodes = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
 }
 
 static void
@@ -306,7 +357,10 @@ arv_gc_finalize (GObject *object)
 {
        ArvGc *genicam = ARV_GC (object);
 
-       g_hash_table_unref (genicam->nodes);
+       if (genicam->priv->buffer != NULL)
+               g_object_weak_unref (G_OBJECT (genicam->priv->buffer), _weak_notify_cb, genicam);
+
+       g_hash_table_unref (genicam->priv->nodes);
 
        parent_class->finalize (object);
 }
@@ -318,6 +372,8 @@ arv_gc_class_init (ArvGcClass *node_class)
        ArvDomNodeClass *d_node_class = ARV_DOM_NODE_CLASS (node_class);
        ArvDomDocumentClass *d_document_class = ARV_DOM_DOCUMENT_CLASS (node_class);
 
+       g_type_class_add_private (node_class, sizeof (ArvGcPrivate));
+
        parent_class = g_type_class_peek_parent (node_class);
 
        object_class->finalize = arv_gc_finalize;
diff --git a/src/arvgc.h b/src/arvgc.h
index 6a76185..0a25052 100644
--- a/src/arvgc.h
+++ b/src/arvgc.h
@@ -35,13 +35,13 @@ G_BEGIN_DECLS
 #define ARV_IS_GC_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ARV_TYPE_GC))
 #define ARV_GC_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), ARV_TYPE_GC, ArvGcClass))
 
+typedef struct _ArvGcPrivate ArvGcPrivate;
 typedef struct _ArvGcClass ArvGcClass;
 
 struct _ArvGc {
        ArvDomDocument base;
 
-       GHashTable *nodes;
-       ArvDevice *device;
+       ArvGcPrivate *priv;
 };
 
 struct _ArvGcClass {
@@ -55,6 +55,8 @@ void                  arv_gc_register_feature_node    (ArvGc *genicam, ArvGcFeatureNode 
*node);
 void                   arv_gc_set_default_node_data    (ArvGc *genicam, const char *node_name, const char 
*node_data);
 ArvGcNode *            arv_gc_get_node                 (ArvGc *genicam, const char *name);
 ArvDevice *            arv_gc_get_device               (ArvGc *genicam);
+void                   arv_gc_set_buffer               (ArvGc *genicam, ArvBuffer *buffer);
+ArvBuffer *            arv_gc_get_buffer               (ArvGc *genicam);
 
 G_END_DECLS
 
diff --git a/src/arvgcport.c b/src/arvgcport.c
index d2888ed..147ea8d 100644
--- a/src/arvgcport.c
+++ b/src/arvgcport.c
@@ -28,18 +28,52 @@
 #include <arvgcport.h>
 #include <arvgcregisterdescriptionnode.h>
 #include <arvdevice.h>
+#include <arvchunkparser.h>
+#include <arvbuffer.h>
+#include <arvgcpropertynode.h>
 #include <arvgc.h>
+#include <memory.h>
 
 static GObjectClass *parent_class = NULL;
 
+struct _ArvGcPortPrivate {
+       ArvGcPropertyNode *chunk_id;
+};
+
 /* ArvDomNode implementation */
 
 static const char *
-arv_gc_port_get_node_name (ArvDomNode *node)
+_get_node_name (ArvDomNode *node)
 {
        return "Port";
 }
 
+static void
+_post_new_child (ArvDomNode *self, ArvDomNode *child)
+{
+       ArvGcPort *node = ARV_GC_PORT (self);
+
+       if (ARV_IS_GC_PROPERTY_NODE (child)) {
+               ArvGcPropertyNode *property_node = ARV_GC_PROPERTY_NODE (child);
+
+               switch (arv_gc_property_node_get_node_type (property_node)) {
+                       case ARV_GC_PROPERTY_NODE_TYPE_CHUNK_ID:
+                               node->priv->chunk_id = property_node;
+                               break;
+                       default:
+                               ARV_DOM_NODE_CLASS (parent_class)->post_new_child (self, child);
+                               break;
+               }
+       } else
+               ARV_DOM_NODE_CLASS (parent_class)->post_new_child (self, child);
+}
+
+static void
+_pre_remove_child (ArvDomNode *self, ArvDomNode *child)
+{
+       g_assert_not_reached ();
+}
+
 /* ArvGcPort implementation */
 
 static gboolean
@@ -58,28 +92,57 @@ void
 arv_gc_port_read (ArvGcPort *port, void *buffer, guint64 address, guint64 length, GError **error)
 {
        ArvGc *genicam;
-       ArvDevice *device;
 
        g_return_if_fail (ARV_IS_GC_PORT (port));
        g_return_if_fail (error == NULL || *error == NULL);
        g_return_if_fail (buffer != NULL);
 
        genicam = arv_gc_node_get_genicam (ARV_GC_NODE (port));
-       device = arv_gc_get_device (genicam);
-
-       /* For schema < 1.1.0 and length == 4, register read must be used instead of memory read.
-        * See Appendix 3 of Genicam 2.0 specification. */
-       if (_register_workaround_check (port, length)) {
-               guint32 value;
-
-               /* For schema < 1.1.0, all registers are big endian. */
-               value = *((guint32 *) buffer);
-               value = GUINT32_FROM_BE (value);
 
-               arv_device_read_register (device, address, &value, error);
-               *((guint32 *) buffer) = GUINT32_TO_BE (value);
-       } else
-               arv_device_read_memory (device, address, length, buffer, error);
+       if (port->priv->chunk_id == NULL) {
+               ArvDevice *device;
+
+               device = arv_gc_get_device (genicam);
+
+               /* For schema < 1.1.0 and length == 4, register read must be used instead of memory read.
+                * See Appendix 3 of Genicam 2.0 specification. */
+               if (_register_workaround_check (port, length)) {
+                       guint32 value;
+
+                       /* For schema < 1.1.0, all registers are big endian. */
+                       value = *((guint32 *) buffer);
+                       value = GUINT32_FROM_BE (value);
+
+                       arv_device_read_register (device, address, &value, error);
+                       *((guint32 *) buffer) = GUINT32_TO_BE (value);
+               } else
+                       arv_device_read_memory (device, address, length, buffer, error);
+       } else {
+               ArvBuffer *chunk_data_buffer;
+
+               chunk_data_buffer = arv_gc_get_buffer (genicam);
+
+               if (!ARV_IS_BUFFER (chunk_data_buffer)) {
+                       if (error != NULL && *error == NULL)
+                               *error = g_error_new (ARV_CHUNK_PARSER_ERROR, 
ARV_CHUNK_PARSER_STATUS_BUFFER_NOT_FOUND,
+                                                     "[ArvGcPort::read] Buffer not found");
+               } else {
+                       char *chunk_data;
+                       size_t chunk_data_size;
+                       guint chunk_id;
+
+                       chunk_id = g_ascii_strtoll (arv_gc_property_node_get_string (port->priv->chunk_id, 
NULL), NULL, 16);
+                       chunk_data = (char *) arv_buffer_get_chunk_data (chunk_data_buffer, chunk_id, 
&chunk_data_size);
+
+                       if (chunk_data != NULL) {
+                               memcpy (buffer, chunk_data + address, MIN (chunk_data_size - address, 
length));
+                       } else {
+                               if (error != NULL && *error == NULL)
+                                       *error = g_error_new (ARV_CHUNK_PARSER_ERROR, 
ARV_CHUNK_PARSER_STATUS_CHUNK_NOT_FOUND,
+                                                             "[ArvGcPort::read] Chunk 0x%08x not found", 
chunk_id);
+                       }
+               }
+       }
 }
 
 void
@@ -93,20 +156,48 @@ arv_gc_port_write (ArvGcPort *port, void *buffer, guint64 address, guint64 lengt
        g_return_if_fail (buffer != NULL);
 
        genicam = arv_gc_node_get_genicam (ARV_GC_NODE (port));
-       device = arv_gc_get_device (genicam);
-
-       /* For schema < 1.1.0 and length == 4, register write must be used instead of memory write.
-        * See Appendix 3 of Genicam 2.0 specification. */
-       if (_register_workaround_check (port, length)) {
-               guint32 value;
-
-               /* For schema < 1.1.0, all registers are big endian. */
-               value = *((guint32 *) buffer);
-               value = GUINT32_FROM_BE (value);
-
-               arv_device_write_register (device, address, value, error);
-       } else
-               arv_device_write_memory (device, address, length, buffer, error);
+       
+       if (port->priv->chunk_id == NULL) {
+               device = arv_gc_get_device (genicam);
+
+               /* For schema < 1.1.0 and length == 4, register write must be used instead of memory write.
+                * See Appendix 3 of Genicam 2.0 specification. */
+               if (_register_workaround_check (port, length)) {
+                       guint32 value;
+
+                       /* For schema < 1.1.0, all registers are big endian. */
+                       value = *((guint32 *) buffer);
+                       value = GUINT32_FROM_BE (value);
+
+                       arv_device_write_register (device, address, value, error);
+               } else
+                       arv_device_write_memory (device, address, length, buffer, error);
+       } else {
+               ArvBuffer *chunk_data_buffer;
+
+               chunk_data_buffer = arv_gc_get_buffer (genicam);
+
+               if (!ARV_IS_BUFFER (chunk_data_buffer)) {
+                       if (error != NULL && *error == NULL)
+                               *error = g_error_new (ARV_CHUNK_PARSER_ERROR, 
ARV_CHUNK_PARSER_STATUS_BUFFER_NOT_FOUND,
+                                                     "[ArvGcPort::write] Buffer not found");
+               } else {
+                       char *chunk_data;
+                       size_t chunk_data_size;
+                       guint chunk_id;
+
+                       chunk_id = g_ascii_strtoll (arv_gc_property_node_get_string (port->priv->chunk_id, 
NULL), NULL, 16);
+                       chunk_data = (char *) arv_buffer_get_chunk_data (chunk_data_buffer, chunk_id, 
&chunk_data_size);
+
+                       if (chunk_data != NULL) {
+                               memcpy (chunk_data + address, buffer, MIN (chunk_data_size - address, 
length));
+                       } else {
+                               if (error != NULL && *error == NULL)
+                                       *error = g_error_new (ARV_CHUNK_PARSER_ERROR, 
ARV_CHUNK_PARSER_STATUS_CHUNK_NOT_FOUND,
+                                                             "[ArvGcPort::write] Chunk 0x%08x not found", 
chunk_id);
+                       }
+               }
+       }
 }
 
 ArvGcNode *
@@ -122,10 +213,12 @@ arv_gc_port_new (void)
 static void
 arv_gc_port_init (ArvGcPort *gc_port)
 {
+       gc_port->priv = G_TYPE_INSTANCE_GET_PRIVATE (gc_port, ARV_TYPE_GC_PORT, ArvGcPortPrivate);
+       gc_port->priv->chunk_id = 0;
 }
 
 static void
-arv_gc_port_finalize (GObject *object)
+_finalize (GObject *object)
 {
        parent_class->finalize (object);
 }
@@ -136,10 +229,14 @@ arv_gc_port_class_init (ArvGcPortClass *this_class)
        GObjectClass *object_class = G_OBJECT_CLASS (this_class);
        ArvDomNodeClass *dom_node_class = ARV_DOM_NODE_CLASS (this_class);
 
+       g_type_class_add_private (this_class, sizeof (ArvGcPortPrivate));
+
        parent_class = g_type_class_peek_parent (this_class);
 
-       object_class->finalize = arv_gc_port_finalize;
-       dom_node_class->get_node_name = arv_gc_port_get_node_name;
+       object_class->finalize = _finalize;
+       dom_node_class->get_node_name = _get_node_name;
+       dom_node_class->post_new_child = _post_new_child;
+       dom_node_class->pre_remove_child = _pre_remove_child;
 }
 
 G_DEFINE_TYPE (ArvGcPort, arv_gc_port, ARV_TYPE_GC_FEATURE_NODE)
diff --git a/src/arvgcport.h b/src/arvgcport.h
index 682bffd..7844155 100644
--- a/src/arvgcport.h
+++ b/src/arvgcport.h
@@ -35,10 +35,13 @@ G_BEGIN_DECLS
 #define ARV_IS_GC_PORT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), ARV_TYPE_GC_PORT))
 #define ARV_GC_PORT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), ARV_TYPE_GC_PORT, ArvGcPortClass))
 
+typedef struct _ArvGcPortPrivate ArvGcPortPrivate;
 typedef struct _ArvGcPortClass ArvGcPortClass;
 
 struct _ArvGcPort {
        ArvGcFeatureNode node;
+
+       ArvGcPortPrivate *priv;
 };
 
 struct _ArvGcPortClass {
diff --git a/src/arvgcpropertynode.c b/src/arvgcpropertynode.c
index c4e1efd..c9e6cd9 100644
--- a/src/arvgcpropertynode.c
+++ b/src/arvgcpropertynode.c
@@ -101,6 +101,8 @@ arv_gc_property_node_get_node_name (ArvDomNode *node)
                        return "Bit";
                case ARV_GC_PROPERTY_NODE_TYPE_COMMAND_VALUE:
                        return "CommandValue";
+               case ARV_GC_PROPERTY_NODE_TYPE_CHUNK_ID:
+                       return "ChunkID";
 
                case ARV_GC_PROPERTY_NODE_TYPE_P_FEATURE:
                        return "pFeature";
@@ -680,6 +682,12 @@ arv_gc_property_node_new_p_command_value (void)
        return arv_gc_property_node_new (ARV_GC_PROPERTY_NODE_TYPE_P_COMMAND_VALUE);
 }
 
+ArvGcNode *
+arv_gc_property_node_new_chunk_id (void)
+{
+       return arv_gc_property_node_new (ARV_GC_PROPERTY_NODE_TYPE_CHUNK_ID);
+}
+
 static void
 arv_gc_property_node_init (ArvGcPropertyNode *gc_property_node)
 {
diff --git a/src/arvgcpropertynode.h b/src/arvgcpropertynode.h
index 072b436..40bed8c 100644
--- a/src/arvgcpropertynode.h
+++ b/src/arvgcpropertynode.h
@@ -56,6 +56,7 @@ typedef enum {
        ARV_GC_PROPERTY_NODE_TYPE_MSB,
        ARV_GC_PROPERTY_NODE_TYPE_BIT,
        ARV_GC_PROPERTY_NODE_TYPE_COMMAND_VALUE,
+       ARV_GC_PROPERTY_NODE_TYPE_CHUNK_ID,
 
        ARV_GC_PROPERTY_NODE_TYPE_P_UNKNONW     = 1000,
        ARV_GC_PROPERTY_NODE_TYPE_P_FEATURE,
@@ -138,6 +139,7 @@ ArvGcNode *         arv_gc_property_node_new_msb                    (void);
 ArvGcNode *    arv_gc_property_node_new_bit                    (void);
 ArvGcNode *    arv_gc_property_node_new_command_value          (void);
 ArvGcNode *    arv_gc_property_node_new_p_command_value        (void);
+ArvGcNode *    arv_gc_property_node_new_chunk_id               (void);
 
 const char *           arv_gc_property_node_get_string         (ArvGcPropertyNode *node, GError **error);
 void                   arv_gc_property_node_set_string         (ArvGcPropertyNode *node, const char *string, 
GError **error);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]