[gegl/meta-json: 12/18] meta-json: Can forward property changes



commit 129da204c97bec3466239cbc2fd964df23815417
Author: Jon Nordby <jononor gmail com>
Date:   Mon Jan 19 22:08:22 2015 +0100

    meta-json: Can forward property changes

 operations/core/json.c |  171 ++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 138 insertions(+), 33 deletions(-)
---
diff --git a/operations/core/json.c b/operations/core/json.c
index a912308..593af7d 100644
--- a/operations/core/json.c
+++ b/operations/core/json.c
@@ -44,15 +44,38 @@ typedef struct _JsonOp
 {
   GeglOperationMetaJson parent_instance;
   JsonObject *json_root;
-  GHashTable *nodes;
+  GHashTable *nodes; // gchar* -> GeglNode *, owned by parent node
 } JsonOp;
 
 typedef struct
 {
   GeglOperationMetaJsonClass parent_class;
   JsonObject *json_root;
+  GHashTable *properties; // guint property_id -> PropertyTarget
 } JsonOpClass;
 
+typedef struct
+{
+  gchar *node;
+  gchar *port;
+} PropertyTarget;
+
+PropertyTarget *
+property_target_new(gchar *node, gchar *port)
+{
+    PropertyTarget *self = g_new(PropertyTarget, 1);
+    self->node = node;
+    self->port = port;
+    return self;
+}
+
+void
+property_target_free(PropertyTarget *self)
+{
+    g_free(self->node);
+    g_free(self->port);
+    g_free(self);
+}
 
 // FIXME: needed?
 /*
@@ -113,7 +136,7 @@ gvalue_from_string(GValue *value, GType target_type, GValue *dest_value) {
     return TRUE;
 }
 
-gboolean
+static gboolean
 set_prop(GeglNode *t, const gchar *port, GParamSpec *paramspec, GValue *value)  {
     GType target_type = G_PARAM_SPEC_VALUE_TYPE(paramspec);
     GValue dest_value = {0,};
@@ -133,7 +156,37 @@ set_prop(GeglNode *t, const gchar *port, GParamSpec *paramspec, GValue *value)
     return FALSE;
 }
 
-static void
+static GParamSpec *
+copy_param_spec(GParamSpec *in, const gchar *name) {
+
+  const gchar * blurb = g_param_spec_get_blurb(in);
+  GParamSpec *out = NULL;
+
+  GParamFlags flags = G_PARAM_READWRITE;
+
+  // TODO: handle more things
+  if (G_IS_PARAM_SPEC_FLOAT(in)) {
+    GParamSpecFloat *f = G_PARAM_SPEC_FLOAT(in);
+    out = g_param_spec_double(name, name, blurb, f->minimum, f->maximum, f->default_value, flags);
+  } else if (G_IS_PARAM_SPEC_DOUBLE(in)) {
+    GParamSpecDouble *d = G_PARAM_SPEC_DOUBLE(in);
+    out = g_param_spec_double(name, name, blurb, d->minimum, d->maximum, d->default_value, flags);
+  } else if (G_IS_PARAM_SPEC_INT(in)) {
+    GParamSpecInt *i = G_PARAM_SPEC_INT(in);
+    out = g_param_spec_int(name, name, blurb, i->minimum, i->maximum, i->default_value, flags);
+  } else if (G_IS_PARAM_SPEC_UINT(in)) {
+    GParamSpecUInt *u = G_PARAM_SPEC_UINT(in);
+    out = g_param_spec_int(name, name, blurb, u->minimum, u->maximum, u->default_value, flags);
+  } else if (G_IS_PARAM_SPEC_LONG(in)) {
+    GParamSpecLong *l = G_PARAM_SPEC_LONG(in);
+    out = g_param_spec_int(name, name, blurb, l->minimum, l->maximum, l->default_value, flags);
+  } else {
+    g_critical("json: Unknown param spec type");
+  }
+  return out;
+}
+
+static guint
 install_properties(JsonOpClass *json_op_class)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (json_op_class);
@@ -152,14 +205,29 @@ install_properties(JsonOpClass *json_op_class)
             JsonObject *conn = json_object_get_object_member(inports, name);
             const gchar *proc = json_object_get_string_member(conn, "process");
             const gchar *port = json_object_get_string_member(conn, "port");
-            GParamSpec *spec = NULL;
-
-            g_print("adding property %s, pointing to %s %s\n", name, port, proc);
-
-            // TODO: look up property on the class/op the port points to and use that paramspec
-            spec = g_param_spec_int (name, name, "DUMMY description", 0, 1000, 1,
-                                        (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
GEGL_PARAM_PAD_INPUT));
-            g_object_class_install_property (object_class, prop++, spec);
+            JsonObject *processes = json_object_get_object_member(root, "processes");
+            JsonObject *p = json_object_get_object_member(processes, proc);
+            const gchar *component = json_object_get_string_member(p, "component");
+
+            {
+              GParamSpec *target_spec = NULL;
+              gchar *opname = component2geglop(component);
+              // HACK: should avoid instantiating node to determine prop
+              GeglNode *n = gegl_node_new();
+              g_assert(n);
+              gegl_node_set(n, "operation", opname, NULL);
+              target_spec = gegl_node_find_property(n, port);
+              if (target_spec) {
+                GParamSpec *spec = copy_param_spec(target_spec, name);
+                g_print("adding property %s, pointing to %s %s\n", name, port, proc);
+                PropertyTarget *t = property_target_new(g_strdup(proc), g_strdup(port));
+                g_hash_table_insert(json_op_class->properties, GINT_TO_POINTER(prop), t);
+                g_object_class_install_property (object_class, prop, spec);
+                prop++;
+              }
+              g_object_unref(n);
+              g_free(opname);
+            }
         }
     }
 
@@ -176,7 +244,7 @@ install_properties(JsonOpClass *json_op_class)
         }
     }
 */
-
+  return prop-1;
 }
 
 static GObject *
@@ -193,19 +261,28 @@ constructor (GType                  type,
   return obj;
 }
 
-
 static void
 get_property (GObject      *gobject,
               guint         property_id,
               GValue       *value,
               GParamSpec   *pspec)
 {
-  switch (property_id)
-  {
-    default:
-//      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
-      break;
+  JsonOpClass * json_op_class = (JsonOpClass *)G_OBJECT_GET_CLASS(gobject);
+  JsonOp * self = (JsonOp *)(gobject);
+
+  PropertyTarget *target = g_hash_table_lookup(json_op_class->properties, property_id);
+  if (!target) {
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec);
+    return;
   }
+
+  GeglNode *node = g_hash_table_lookup(self->nodes, target->node);  
+  if (!node) {
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec);
+    return;
+  }
+
+  gegl_node_get_property(node, target->port, value);
 }
 
 static void
@@ -214,12 +291,23 @@ set_property (GObject      *gobject,
               const GValue *value,
               GParamSpec   *pspec)
 {
-  switch (property_id)
-  {
-    default:
-//      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
-      break;
+  JsonOpClass * json_op_class = (JsonOpClass *)G_OBJECT_GET_CLASS(gobject);
+  JsonOp * self = (JsonOp *)(gobject);
+  g_assert(self);
+
+  PropertyTarget *target = g_hash_table_lookup(json_op_class->properties, property_id);
+  if (!target) {
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec);
+    return;
   }
+
+  GeglNode *node = g_hash_table_lookup(self->nodes, target->node);  
+  if (!node) {
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec);
+    return;
+  }
+
+  gegl_node_set_property(node, target->port, value);
 }
 
 static void
@@ -241,6 +329,7 @@ attach (GeglOperation *operation)
       g_print("creating node %s with operation %s\n", name, opname);
       GeglNode *node = gegl_node_new_child (gegl, "operation", opname, NULL);
       gegl_operation_meta_watch_node (operation, node);
+      g_assert(node);
       g_hash_table_insert(self->nodes, (gpointer)g_strdup(name), (gpointer)node);
       g_free(opname);
   }
@@ -333,6 +422,23 @@ attach (GeglOperation *operation)
 }
 
 static void
+json_op_init (JsonOp *self)
+{
+  self->nodes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+}
+
+static void
+finalize (GObject *gobject)
+{
+  JsonOp *self = (JsonOp *)(gobject);
+  JsonOpClass *json_op_class = (JsonOpClass *)G_OBJECT_GET_CLASS(gobject);
+
+  g_hash_table_unref (self->nodes);
+
+// FIXME: causes infinite loop GEGL_OPERATION_CLASS(json_op_class)->finalize(gobject);
+}
+
+static void
 json_op_class_init (gpointer klass, gpointer class_data)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -343,14 +449,17 @@ json_op_class_init (gpointer klass, gpointer class_data)
   object_class->set_property = set_property;
   object_class->get_property = get_property;
   object_class->constructor  = constructor;
+  object_class->finalize = finalize;
 
   operation_class->attach = attach;
 
+  json_op_class->properties = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                                                    NULL, (GDestroyNotify)property_target_free);
   install_properties(json_op_class);
 
   // FIXME: unharcode, look up in properties
   gegl_operation_class_set_keys (operation_class,
-    "name",        "gegl:dropshadow2",
+    "name",        "gegl:greyy",
     "categories",  "effects:light",
     "description", "Creates a dropshadow effect on the input buffer",
     NULL);
@@ -360,15 +469,10 @@ json_op_class_init (gpointer klass, gpointer class_data)
 static void
 json_op_class_finalize (JsonOpClass *self)
 {
-}     
-
-
-static void
-json_op_init (JsonOp *self)
-{
-  self->nodes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); // FIXME: free
+  g_hash_table_unref(self->properties);
 }
 
+
 static GType                                                             
 json_op_register_type (GTypeModule *type_module, const gchar *name, gpointer klass_data)                    
 {
@@ -408,7 +512,7 @@ json_op_register_type_for_file (GTypeModule *type_module, const gchar *filepath)
         g_assert(root_node);
         g_print("%s: %p\n", __PRETTY_FUNCTION__, root_node);
         // FIXME: unhardoce name, look up in json structure, fallback to basename
-        ret = json_op_register_type(type_module, "dropshadow_json", root);
+        ret = json_op_register_type(type_module, "grey_json", root);
     }
 
 //    g_object_unref(parser);
@@ -421,7 +525,8 @@ static void
 json_register_operations(GTypeModule *module)
 {
     // FIXME: unhardcode, follow GEGL_PATH properly
-    json_op_register_type_for_file (module, JSON_OP_DIR "/dropshadow2.json");
+//    json_op_register_type_for_file (module, JSON_OP_DIR "/dropshadow2.json");
+    json_op_register_type_for_file (module, JSON_OP_DIR "/grey2.json");
 }
 
 


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