[telepathy-mission-control/master] mcd-dbusprop: implement getting dbus properties asynchronously

Jonny Lamb jonny.lamb at collabora.co.uk
Mon Sep 14 11:09:15 PDT 2009


Getting the Parameters property is still broken because the Parameters
property hasn't implemented an async get function.

Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
---
 src/mcd-dbusprop.c |  145 ++++++++++++++++++++++++++++++++++++++-------------
 src/mcd-dbusprop.h |    9 +++-
 2 files changed, 116 insertions(+), 38 deletions(-)

diff --git a/src/mcd-dbusprop.c b/src/mcd-dbusprop.c
index 4c61bf4..3d075d7 100644
--- a/src/mcd-dbusprop.c
+++ b/src/mcd-dbusprop.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 #include <telepathy-glib/errors.h>
+#include <telepathy-glib/util.h>
 #include "mcd-dbusprop.h"
 #include "mcd-debug.h"
 
@@ -173,74 +174,144 @@ mcd_dbusprop_get_property (TpSvcDBusProperties *self,
     return TRUE;
 }
 
+static void
+dbusprop_get_cb (TpSvcDBusProperties *self, const GValue *value,
+                 const GError *error, gpointer user_data)
+{
+  DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
+
+  tp_svc_dbus_properties_return_from_get (context, value);
+}
+
 void
 dbusprop_get (TpSvcDBusProperties *self,
-	      const gchar *interface_name,
-	      const gchar *property_name,
-	      DBusGMethodInvocation *context)
+              const gchar *interface_name,
+              const gchar *property_name,
+              DBusGMethodInvocation *context)
 {
     GValue value = { 0 };
     GError *error = NULL;
+    const McdDBusProp *property;
 
     DEBUG ("%s, %s", interface_name, property_name);
 
-    mcd_dbusprop_get_property (self, interface_name, property_name,
-			       &value, &error);
-    if (error)
+    /* Look whether the property can support async getting */
+    property = get_mcddbusprop (self, interface_name, property_name, NULL);
+    if (property != NULL && property->async_getprop != NULL)
     {
-	dbus_g_method_return_error (context, error);
-	g_error_free (error);
-	return;
+      property->async_getprop (self, property_name, dbusprop_get_cb, context);
+    }
+    else
+    {
+        /* The normal route */
+        mcd_dbusprop_get_property (self, interface_name, property_name,
+                                   &value, &error);
+
+        if (error)
+        {
+            dbus_g_method_return_error (context, error);
+            g_error_free (error);
+            return;
+        }
+
+        tp_svc_dbus_properties_return_from_get (context, &value);
+        g_value_unset (&value);
     }
-
-    tp_svc_dbus_properties_return_from_get (context, &value);
-    g_value_unset (&value);
 }
 
+typedef struct
+{
+    TpSvcDBusProperties *self;
+    DBusGMethodInvocation *context;
+    GHashTable *properties;
+    const McdDBusProp *property;
+} GetAllData;
+
 static void
-free_prop_val (gpointer val)
+get_all_iter (TpSvcDBusProperties *self,
+              const GValue *value,
+              const GError *error,
+              gpointer user_data)
 {
-    GValue *value = val;
+    GetAllData *data = (GetAllData *) user_data;
 
-    g_value_unset (value);
-    g_free (value);
+    if (self != NULL && value != NULL)
+    {
+        /* This is actually a callback */
+        g_hash_table_insert (data->properties, (gchar *) data->property->name,
+                             tp_g_value_slice_dup (value));
+
+        data->property++;
+    }
+
+    if (data->property->name != NULL)
+    {
+        if (data->property->async_getprop)
+        {
+          data->property->async_getprop (data->self, data->property->name,
+                                         get_all_iter, data);
+        }
+        else if (data->property->getprop)
+        {
+            GValue *out;
+
+            out = g_malloc0 (sizeof (GValue));
+            data->property->getprop (data->self, data->property->name, out);
+            g_hash_table_insert (data->properties, (gchar *) data->property->name,
+                tp_g_value_slice_dup (out));
+            g_value_unset (out);
+            g_free (out);
+
+            data->property++;
+            get_all_iter (NULL, NULL, NULL, data);
+        }
+        else
+        {
+            data->property++;
+            get_all_iter (NULL, NULL, NULL, data);
+        }
+    }
+    else
+    {
+      tp_svc_dbus_properties_return_from_get_all (data->context,
+                                                  data->properties);
+      g_hash_table_destroy (data->properties);
+      g_slice_free (GetAllData, data);
+
+    }
 }
 
 void
 dbusprop_get_all (TpSvcDBusProperties *self,
-		  const gchar *interface_name,
-		  DBusGMethodInvocation *context)
+                  const gchar *interface_name,
+                  DBusGMethodInvocation *context)
 {
-    const McdDBusProp *prop_array, *property;
-    GHashTable *properties;
+    const McdDBusProp *prop_array;
     GError *error = NULL;
+    GetAllData *data;
 
     DEBUG ("%s", interface_name);
 
     prop_array = get_interface_properties (self, interface_name);
     if (!prop_array)
     {
-	g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
-		     "invalid interface: %s", interface_name);
-	dbus_g_method_return_error (context, error);
-	g_error_free (error);
-	return;
+        g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+                     "invalid interface: %s", interface_name);
+        dbus_g_method_return_error (context, error);
+        g_error_free (error);
+        return;
     }
 
-    properties = g_hash_table_new_full (g_str_hash, g_str_equal,
-					NULL, free_prop_val);
-    for (property = prop_array; property->name != NULL; property++)
-    {
-	GValue *value;
+    data = g_slice_new0 (GetAllData);
+    data->self = self;
+    data->context = context;
 
-	if (!property->getprop) continue;
+    data->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                              NULL, (GDestroyNotify) tp_g_value_slice_free);
 
-	value = g_malloc0 (sizeof (GValue));
-	property->getprop (self, property->name, value);
-	g_hash_table_insert (properties, (gchar *)property->name, value);
-    }
-    tp_svc_dbus_properties_return_from_get_all (context, properties);
-    g_hash_table_destroy (properties);
+    data->property = prop_array;
+
+    get_all_iter (NULL, NULL, NULL, data);
 }
 
 void
diff --git a/src/mcd-dbusprop.h b/src/mcd-dbusprop.h
index 77c50c8..a6cd5e1 100644
--- a/src/mcd-dbusprop.h
+++ b/src/mcd-dbusprop.h
@@ -34,7 +34,13 @@ G_BEGIN_DECLS
 typedef gboolean (*mcd_setprop) (TpSvcDBusProperties *self, const gchar *name,
                                  const GValue *value, GError **error);
 typedef void (*mcd_getprop) (TpSvcDBusProperties *self, const gchar *name,
-			     GValue *value);
+                             GValue *value);
+
+typedef void (*mcddbus_get_cb) (TpSvcDBusProperties *self, const GValue *value,
+                                const GError *error, gpointer user_data);
+typedef void (*mcd_async_getprop) (TpSvcDBusProperties *self, const gchar *name,
+                                   mcddbus_get_cb callback, gpointer user_data);
+
 typedef void (*McdInterfaceInit) (TpSvcDBusProperties *self);
 
 typedef struct _McdDBusProp
@@ -42,6 +48,7 @@ typedef struct _McdDBusProp
     const gchar *name;
     mcd_setprop setprop;
     mcd_getprop getprop;
+    mcd_async_getprop async_getprop;
 } McdDBusProp;
 
 typedef struct _McdInterfaceData
-- 
1.5.6.5




More information about the telepathy-commits mailing list