--- libvisual/visual.c	2009-07-14 05:03:45.000000000 -0500
+++ libvisual-new/visual.c	2010-01-13 22:17:06.570627211 -0600
@@ -36,10 +36,18 @@
 
 typedef struct _GstVisual GstVisual;
 typedef struct _GstVisualClass GstVisualClass;
+typedef struct _ParamQueueEntry ParamQueueEntry;
 
 GST_DEBUG_CATEGORY_STATIC (libvisual_debug);
 #define GST_CAT_DEFAULT (libvisual_debug)
 
+struct _ParamQueueEntry {
+    GObject *object;
+    guint prop_id;
+    GValue set_value;
+    GParamSpec *pspec;
+};
+
 struct _GstVisual
 {
   GstElement element;
@@ -77,6 +85,13 @@
   /* QoS stuff *//* with LOCK */
   gdouble proportion;
   GstClockTime earliest_time;
+
+  /* Param get and set queues */
+  VisList set_property_queue;
+  int set_property_flag;
+
+  /* actor realized? */
+  int actor_realized;
 };
 
 struct _GstVisualClass
@@ -88,7 +103,6 @@
 
 GType gst_visual_get_type (void);
 
-
 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
@@ -133,6 +147,22 @@
 static GstCaps *gst_visual_getcaps (GstPad * pad);
 static void libvisual_log_handler (const char *message, const char *funcname,
     void *priv);
+static void gst_visual_install_params(GstVisualClass *klass);
+static void gst_visual_set_property  (GObject      *object,
+                         guint         prop_id,
+                         GValue *value,
+                         GParamSpec   *pspec);
+static void _gst_visual_set_property  (GObject      *object,
+                         guint         prop_id,
+                         const GValue *value,
+                         GParamSpec   *pspec);
+static void _gst_visual_get_property  (GObject      *object,
+                         guint         prop_id,
+                         GValue       *value,
+                         GParamSpec   *pspec);
+static void gst_visual_handle_property_changes(GstVisual *visual);
+static void make_valid_name (char *name);
+
 
 static GstElementClass *parent_class = NULL;
 
@@ -199,12 +229,252 @@
     g_free (details.longname);
   }
 
+  gst_visual_install_params(klass);
+
   object->dispose = gst_visual_dispose;
 }
 
 static void
+gst_visual_install_params(GstVisualClass *class) 
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(class);
+    VisParamContainer *params;
+    VisParamEntry *param;
+    VisList *list, *plist;
+    VisPluginData *visplugin = NULL;
+    char *name;
+    int param_count, j;
+
+    object_class->set_property = _gst_visual_set_property;
+    object_class->get_property = _gst_visual_get_property;
+
+    list = visual_actor_get_list ();
+
+    if(!visual_is_initialized())
+        visual_init(0, NULL);
+
+    if(class->plugin == NULL)
+        return;
+
+    visplugin = visual_plugin_load (class->plugin);
+
+    visual_log_return_if_fail(visplugin != NULL);
+    
+    visual_plugin_realize(visplugin);
+
+    params = visual_plugin_get_params(visplugin);
+    visual_log_return_if_fail(params != NULL);
+
+    plist = &params->entries;
+    visual_log_return_if_fail(list != NULL);
+
+    param_count = plist->count;
+
+    for(j = 0; j < param_count; j++) {
+        param = visual_list_get(plist, j);
+        if(param == NULL) {
+            continue;
+        }
+
+        name = visual_param_entry_get_name(param);
+        make_valid_name(name);
+
+        switch(param->type) {
+        case VISUAL_PARAM_ENTRY_TYPE_STRING:
+            g_object_class_install_property(object_class, j + 1,
+                g_param_spec_string(name, name, "Please read actor documentation", 
+                    "", G_PARAM_READWRITE));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_INTEGER:
+            g_object_class_install_property(object_class, j + 1,
+                g_param_spec_int(name, name, "Please read actor documentation", 
+                    INT_MIN, INT_MAX, 0, G_PARAM_READWRITE));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_FLOAT:
+            g_object_class_install_property(object_class, j + 1,
+                g_param_spec_float(name, name, "Please read actor documentation", 
+                    FLT_MIN, FLT_MAX, 0.0, G_PARAM_READWRITE));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_DOUBLE:
+            g_object_class_install_property(object_class, j + 1,
+                g_param_spec_double(name, name, "Please read actor documentation", 
+                    DBL_MIN, DBL_MAX, 0.0, G_PARAM_READWRITE));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_COLOR:
+            g_object_class_install_property(object_class, j + 1,
+                g_param_spec_uint(name, name, "Please read actor documentation",
+                    0, UINT_MAX, 0x0, G_PARAM_READWRITE));
+            break;
+        default:
+            break;
+        }
+    }
+
+    visual_plugin_unload (visplugin);
+}
+
+
+static void _gst_visual_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+    GstVisual *visual = GST_VISUAL(object);
+    ParamQueueEntry *entry = visual_mem_malloc0(sizeof(ParamQueueEntry));
+
+    entry->object = object;
+    entry->prop_id = prop_id;
+    g_value_init(&entry->set_value, G_VALUE_TYPE(value));
+    g_value_copy(value, &entry->set_value);
+    entry->pspec = pspec;
+
+    visual_list_add(&visual->set_property_queue, entry);
+    visual->set_property_flag = TRUE;
+
+    gst_visual_handle_property_changes(visual);
+}
+
+static void gst_visual_set_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) 
+{
+    GstVisual *visual = GST_VISUAL(object);
+    VisParamContainer *params;
+    VisPluginInfo *info;
+    VisParamEntry *param;
+    VisList *list;
+    VisColor color;
+    VisPluginData *plugin;
+    int count;
+
+    visual_log_return_if_fail(visual->actor);
+
+    plugin = visual_actor_get_plugin(visual->actor);
+    visual_log_return_if_fail(plugin != NULL);
+
+    info = visual_plugin_get_info(plugin);
+
+    params = visual_plugin_get_params(plugin);
+    visual_log_return_if_fail(params != NULL);
+
+    list = &params->entries;
+    visual_log_return_if_fail(list != NULL);
+
+    count = list->count;
+
+    param = (VisParamEntry *)visual_list_get(list, prop_id - 1);
+
+    switch(visual_param_entry_get_type(param)) {
+        case VISUAL_PARAM_ENTRY_TYPE_STRING:
+            visual_param_entry_set_string(param, (char *)g_value_get_string(value));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_INTEGER:
+            visual_param_entry_set_integer(param, g_value_get_int(value));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_FLOAT:
+            visual_param_entry_set_float(param, g_value_get_float(value));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_DOUBLE:
+            visual_param_entry_set_double(param, g_value_get_double(value));
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_COLOR:
+            visual_color_from_uint32(&color, g_value_get_int(value));
+            visual_param_entry_set_color_by_color(param, &color);
+            break;
+        default:
+            break;
+    }
+}
+
+static void _gst_visual_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) 
+{
+    GstVisual *visual = GST_VISUAL(object);
+    VisParamContainer *params;
+    VisPluginInfo *info;
+    VisParamEntry *param;
+    VisList *list;
+    VisPluginData *plugin;
+    int count;
+    char *s;
+    int i;
+    float f;
+    double d;
+    VisColor *c;
+
+    if(visual->actor == NULL)
+        return;
+
+    plugin = visual_actor_get_plugin(visual->actor);
+
+    visual_log_return_if_fail(plugin != NULL);
+
+    info = visual_plugin_get_info(plugin);
+
+    params = visual_plugin_get_params(plugin);
+    visual_log_return_if_fail(params != NULL);
+
+    list = &params->entries;
+    visual_log_return_if_fail(list != NULL);
+
+    count = list->count;
+
+    param = (VisParamEntry *)visual_list_get(list, prop_id - 1);
+
+    switch(visual_param_entry_get_type(param)) {
+        case VISUAL_PARAM_ENTRY_TYPE_STRING:
+            s = visual_param_entry_get_string(param);
+            g_value_set_string(value, s);
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_INTEGER:
+            i = visual_param_entry_get_integer(param);
+            g_value_set_int(value, i);
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_FLOAT:
+            f = visual_param_entry_get_float(param);
+            g_value_set_float(value, f);
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_DOUBLE:
+            d = visual_param_entry_get_double(param);
+            g_value_set_double(value, d);
+            break;
+        case VISUAL_PARAM_ENTRY_TYPE_COLOR:
+            c = visual_param_entry_get_color(param);
+            g_value_set_uint(value, visual_color_to_uint32(c));
+            break;
+        default:
+            break;
+    }
+}
+
+void gst_visual_handle_property_changes(GstVisual *visual)
+{
+  /* Check if property changes are queued */
+  if(visual->set_property_flag && visual->actor_realized) {
+    int count = visual_collection_size(VISUAL_COLLECTION(&visual->set_property_queue));
+    int i;
+    for(i = count - 1; count >= 0; i--) {
+      VisListEntry *entry = visual->set_property_queue.head;
+      ParamQueueEntry *qentry;
+      int j;
+      for(j = 0; j < i && entry; j++)
+        entry = entry->next;
+      if(entry == NULL)
+        break;
+      qentry = entry->data;
+      gst_visual_set_property(qentry->object, qentry->prop_id, &qentry->set_value, qentry->pspec);
+      visual_list_destroy(&visual->set_property_queue, &entry);
+    }
+    visual->set_property_flag = FALSE;
+  }
+
+}
+
+int gst_visual_queue_destroyer(void *data)
+{
+    visual_log_return_val_if_fail(data != NULL, -1);
+    visual_mem_free(data);
+    return 0;
+}
+
+static void
 gst_visual_init (GstVisual * visual)
 {
+
   /* create the sink and src pads */
   visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
   gst_pad_set_setcaps_function (visual->sinkpad, gst_visual_sink_setcaps);
@@ -219,6 +489,9 @@
   gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad);
 
   visual->adapter = gst_adapter_new ();
+
+  visual_collection_set_destroyer(VISUAL_COLLECTION(&visual->set_property_queue), 
+    gst_visual_queue_destroyer);
 }
 
 static void
@@ -772,6 +1045,12 @@
       if (visual_actor_realize (visual->actor) != 0)
         goto no_realize;
 
+      visual->actor_realized = TRUE;
+
+      visual_plugin_events_pump(visual->actor->plugin);
+
+      gst_visual_handle_property_changes(visual);
+
       visual_actor_set_video (visual->actor, visual->video);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
@@ -958,3 +1237,4 @@
     "libvisual",
     "libvisual visualization plugins",
     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+
