]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
2005-07-08 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Sat, 9 Jul 2005 01:46:51 +0000 (01:46 +0000)
committerColin Walters <walters@verbum.org>
Sat, 9 Jul 2005 01:46:51 +0000 (01:46 +0000)
* test/glib/test-service-glib.xml:
* test/glib/test-service-glib.c:
* test/glib/test-dbus-glib.c: Test a{sv}.

* glib/examples/statemachine/statemachine.c:
* glib/examples/statemachine/statemachine-server.c:
* glib/examples/statemachine/statemachine-client.c: Fix some bugs,
add progress bar, etc.

* glib/dbus-gvalue.c (register_array, register_dict): Delete; not
needed anymore due to generic array/map marshalling.
(dbus_g_value_types_init): Don't register basic arrays or the
string/string hash.
(dbus_gtype_from_signature_iter): Don't try to recurse into
variants.
(dbus_gtype_to_signature): Check collection/map before type
metadata.
(demarshal_garray_basic): Renamed to demarshal_collection_array.
(demarshal_ghashtable): Renamed to demarshal_map; fix to use new
generic map creation/append functions instead of hash table
specifically.
(get_type_demarshaller): Handle maps.
(demarshal_collection): Dispatch on collection type to either
demarshal_collection_ptrarray or demarshal_collection_array.
(get_type_marshaller): Handle maps.
(marshal_collection): Dispatch collection type to either
marshal_collection_ptrarray or marshal_collection_array.
(_dbus_gvalue_test): New test.

* glib/dbus-gvalue-utils.c (unset_and_free_g_value): New function.
(hash_free_from_gtype): Use it to free GValues.
(hashtable_append): New function.
(ptrarray_append): Fix prototype.
(slist_append): Ditto.
(_dbus_gvalue_utils_test): Extend tests.

* glib/dbus-gtype-specialized.c
(dbus_g_type_specialized_init_append): Renamed from
dbus_g_type_specialized_collection_init_append.  Remove const from
value, since we steal it.
(dbus_g_type_specialized_map_append): New function.

* glib/dbus-gtype-specialized.h: Update prototypes.
Add DBusGTypeSpecializedMapAppendFunc.

* glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run
_dbus_gvalue_test.

* glib/dbus-gtest.h: Prototype it.

13 files changed:
ChangeLog
glib/dbus-gtest.c
glib/dbus-gtest.h
glib/dbus-gtype-specialized.c
glib/dbus-gtype-specialized.h
glib/dbus-gvalue-utils.c
glib/dbus-gvalue.c
glib/examples/statemachine/statemachine-client.c
glib/examples/statemachine/statemachine-server.c
glib/examples/statemachine/statemachine.c
test/glib/test-dbus-glib.c
test/glib/test-service-glib.c
test/glib/test-service-glib.xml

index 9ad68040d71ecd9d0ae41b56242cfe3c5dd229af..f98a6e7603752d049daee357ef9b570faf6823f8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2005-07-08  Colin Walters  <walters@verbum.org>
+
+       * test/glib/test-service-glib.xml: 
+       * test/glib/test-service-glib.c:
+       * test/glib/test-dbus-glib.c: Test a{sv}.
+
+       * glib/examples/statemachine/statemachine.c:
+       * glib/examples/statemachine/statemachine-server.c:
+       * glib/examples/statemachine/statemachine-client.c: Fix some bugs,
+       add progress bar, etc.
+
+       * glib/dbus-gvalue.c (register_array, register_dict): Delete; not
+       needed anymore due to generic array/map marshalling.
+       (dbus_g_value_types_init): Don't register basic arrays or the
+       string/string hash.
+       (dbus_gtype_from_signature_iter): Don't try to recurse into
+       variants.
+       (dbus_gtype_to_signature): Check collection/map before type
+       metadata.
+       (demarshal_garray_basic): Renamed to demarshal_collection_array.
+       (demarshal_ghashtable): Renamed to demarshal_map; fix to use new
+       generic map creation/append functions instead of hash table
+       specifically.
+       (get_type_demarshaller): Handle maps.
+       (demarshal_collection): Dispatch on collection type to either
+       demarshal_collection_ptrarray or demarshal_collection_array.
+       (get_type_marshaller): Handle maps.
+       (marshal_collection): Dispatch collection type to either
+       marshal_collection_ptrarray or marshal_collection_array.
+       (_dbus_gvalue_test): New test.
+
+       * glib/dbus-gvalue-utils.c (unset_and_free_g_value): New function.
+       (hash_free_from_gtype): Use it to free GValues.
+       (hashtable_append): New function.
+       (ptrarray_append): Fix prototype.
+       (slist_append): Ditto.
+       (_dbus_gvalue_utils_test): Extend tests.
+
+       * glib/dbus-gtype-specialized.c
+       (dbus_g_type_specialized_init_append): Renamed from
+       dbus_g_type_specialized_collection_init_append.  Remove const from
+       value, since we steal it.
+       (dbus_g_type_specialized_map_append): New function.
+
+       * glib/dbus-gtype-specialized.h: Update prototypes.
+       Add DBusGTypeSpecializedMapAppendFunc.
+
+       * glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run
+       _dbus_gvalue_test.
+       
+       * glib/dbus-gtest.h: Prototype it.
+
 2005-07-08  Ross Burton  <ross@openedhand.com>
 
        * dbus/dbus-glib.h:
index 2b79feb4f5a178c9faadb718a293f16a833a5dda..e5c2e8b95963c82e349f5b6731e7787d75d2fdff 100644 (file)
@@ -63,6 +63,10 @@ dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir)
   if (!_dbus_gvalue_utils_test (test_data_dir))
     die ("gvalue utils");
 
+  printf ("%s: running GValue tests\n", "dbus-glib-test");
+  if (!_dbus_gvalue_test (test_data_dir))
+    die ("gvalue utils");
+
   printf ("%s: running glib tests\n", "dbus-glib-test");
   if (!_dbus_glib_test (test_data_dir))
     die ("glib");
index 73bf0dda2c677c41cb2299c0a9dcbe9a78cfd018..75633ea71a2174f17ad1098bdf149fc40decf97c 100644 (file)
@@ -30,6 +30,7 @@ gboolean _dbus_gmain_test   (const char *test_data_dir);
 gboolean _dbus_gobject_test (const char *test_data_dir);
 gboolean _dbus_gutils_test  (const char *test_data_dir);
 gboolean _dbus_glib_test    (const char *test_data_dir);
+gboolean _dbus_gvalue_test  (const char *test_data_dir);
 gboolean _dbus_gvalue_utils_test    (const char *test_data_dir);
 
 void dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir);
index d588fa8638c2e05297d0a6a366ddf9acb8c29988..ccf65eef5404c3133b1a5427df497ef039477091 100644 (file)
@@ -427,7 +427,7 @@ typedef struct {
 } DBusGTypeSpecializedAppendContextReal;
 
 void
-dbus_g_type_specialized_collection_init_append (GValue *value, DBusGTypeSpecializedAppendContext *ctx)
+dbus_g_type_specialized_init_append (GValue *value, DBusGTypeSpecializedAppendContext *ctx)
 {
   DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
   GType gtype;
@@ -446,7 +446,7 @@ dbus_g_type_specialized_collection_init_append (GValue *value, DBusGTypeSpeciali
 
 void
 dbus_g_type_specialized_collection_append (DBusGTypeSpecializedAppendContext *ctx,
-                                          const GValue *elt)
+                                          GValue                            *elt)
 {
   DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
   ((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->append_func (ctx, elt);
@@ -460,6 +460,15 @@ dbus_g_type_specialized_collection_end_append (DBusGTypeSpecializedAppendContext
     ((DBusGTypeSpecializedCollectionVtable *) realctx->specdata->klass->vtable)->end_append_func (ctx);
 }
 
+void
+dbus_g_type_specialized_map_append (DBusGTypeSpecializedAppendContext *ctx,
+                                   GValue                            *key,
+                                   GValue                            *val)
+{
+  DBusGTypeSpecializedAppendContextReal *realctx = (DBusGTypeSpecializedAppendContextReal *) ctx;
+  ((DBusGTypeSpecializedMapVtable *) realctx->specdata->klass->vtable)->append_func (ctx, key, val);
+}
+
 void
 dbus_g_type_map_value_iterate (const GValue                           *value,
                               DBusGTypeSpecializedMapIterator         iterator,
index 8e47db981b512dea46550ec0041fd3088b8c59a5..e95af3e5f7fa86987108d217b107137267672a5d 100644 (file)
@@ -58,12 +58,17 @@ typedef struct {
   gpointer d;
 } DBusGTypeSpecializedAppendContext;
 
-void           dbus_g_type_specialized_collection_init_append  (GValue *val, DBusGTypeSpecializedAppendContext *ctx);
+void           dbus_g_type_specialized_init_append             (GValue *val, DBusGTypeSpecializedAppendContext *ctx);
 
-void           dbus_g_type_specialized_collection_append       (DBusGTypeSpecializedAppendContext *ctx, const GValue *elt);
+void           dbus_g_type_specialized_collection_append       (DBusGTypeSpecializedAppendContext *ctx, GValue *elt);
 
 void           dbus_g_type_specialized_collection_end_append   (DBusGTypeSpecializedAppendContext *ctx);
 
+void           dbus_g_type_specialized_map_append              (DBusGTypeSpecializedAppendContext *ctx,
+                                                               GValue                            *key,
+                                                               GValue                            *val);
+                                                               
+
 gboolean       dbus_g_type_collection_get_fixed             (GValue                                 *value,
                                                             gpointer                               *data,
                                                             guint                                  *len);
@@ -90,8 +95,8 @@ typedef struct {
 } DBusGTypeSpecializedVtable;
 
 typedef gboolean (*DBusGTypeSpecializedCollectionFixedAccessorFunc) (GType type, gpointer instance, gpointer *values, guint *len);
-typedef void (*DBusGTypeSpecializedCollectionIteratorFunc)          (GType type, gpointer instance, DBusGTypeSpecializedCollectionIterator iterator, gpointer user_data);
-typedef void     (*DBusGTypeSpecializedCollectionAppendFunc)        (DBusGTypeSpecializedAppendContext *ctx, const GValue *val);
+typedef void     (*DBusGTypeSpecializedCollectionIteratorFunc)      (GType type, gpointer instance, DBusGTypeSpecializedCollectionIterator iterator, gpointer user_data);
+typedef void     (*DBusGTypeSpecializedCollectionAppendFunc)        (DBusGTypeSpecializedAppendContext *ctx, GValue *val);
 typedef void     (*DBusGTypeSpecializedCollectionEndAppendFunc)     (DBusGTypeSpecializedAppendContext *ctx);
 
 typedef struct {
@@ -103,10 +108,12 @@ typedef struct {
 } DBusGTypeSpecializedCollectionVtable;
 
 typedef void (*DBusGTypeSpecializedMapIteratorFunc) (GType type, gpointer instance, DBusGTypeSpecializedMapIterator iterator, gpointer user_data);
+typedef void (*DBusGTypeSpecializedMapAppendFunc)   (DBusGTypeSpecializedAppendContext *ctx, GValue *key, GValue *val);
 
 typedef struct {
   DBusGTypeSpecializedVtable                        base_vtable;
   DBusGTypeSpecializedMapIteratorFunc               iterator;
+  DBusGTypeSpecializedMapAppendFunc                 append_func;
 } DBusGTypeSpecializedMapVtable;
 
 void           dbus_g_type_specialized_init           (void);
index b281f6ee38162a30b3072617f62d4cc1aa2e4d44..b17eee162faf5a766a8dc428e9a612c749763ed7 100644 (file)
@@ -226,6 +226,15 @@ hash_func_from_gtype (GType gtype, GHashFunc *func)
     }
 }
 
+static void
+unset_and_free_g_value (gpointer val)
+{
+  GValue *value = val;
+
+  g_value_unset (value);
+  g_free (value);
+}
+
 static gboolean
 hash_free_from_gtype (GType gtype, GDestroyNotify *func)
 {
@@ -244,7 +253,7 @@ hash_free_from_gtype (GType gtype, GDestroyNotify *func)
     default:
       if (gtype == G_TYPE_VALUE)
        {
-         *func = (GDestroyNotify) g_value_unset;
+         *func = unset_and_free_g_value;
          return TRUE;
        }
       return FALSE;
@@ -441,6 +450,17 @@ dbus_g_hash_table_insert_steal_values (GHashTable *table,
   g_hash_table_insert (table, key, val);
 }
 
+static void
+hashtable_append (DBusGTypeSpecializedAppendContext *ctx,
+                 GValue                            *key,
+                 GValue                            *val)
+{
+  GHashTable *table;
+
+  table = g_value_get_boxed (ctx->val);
+  dbus_g_hash_table_insert_steal_values (table, key, val);
+}
+
 static gpointer
 hashtable_constructor (GType type)
 {
@@ -667,7 +687,7 @@ ptrarray_copy (GType type, gpointer src)
 }
 
 static void
-ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, const GValue *value)
+ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
 {
   GPtrArray *array;
 
@@ -740,7 +760,7 @@ slist_copy (GType type, gpointer src)
 }
 
 static void
-slist_append (DBusGTypeSpecializedAppendContext *ctx, const GValue *value)
+slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
 {
   GSList *list;
 
@@ -822,7 +842,8 @@ dbus_g_type_specialized_builtins_init (void)
       NULL,
       NULL
     },
-    hashtable_iterator
+    hashtable_iterator,
+    hashtable_append
   };
 
   dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0);
@@ -860,6 +881,35 @@ test_specialized_hash (const GValue *key, const GValue *val, gpointer user_data)
     }
 }
 
+static void
+test_specialized_hash_2 (const GValue *key, const GValue *val, gpointer user_data)
+{
+  TestSpecializedHashData *data = user_data;
+  const GValue *realval;
+
+  g_assert (G_VALUE_HOLDS_STRING (key));
+  g_assert (G_VALUE_TYPE (val) == G_TYPE_VALUE);
+
+  realval = g_value_get_boxed (val);
+
+  if (!strcmp (g_value_get_string (key), "foo"))
+    {
+      data->seen_foo = TRUE;
+      g_assert (G_VALUE_HOLDS_UINT (realval));
+      g_assert (g_value_get_uint (realval) == 20);
+    }
+  else if (!strcmp (g_value_get_string (key), "baz"))
+    {
+      data->seen_baz = TRUE;
+      g_assert (G_VALUE_HOLDS_STRING (realval));
+      g_assert (!strcmp ("bar", g_value_get_string (realval)));
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+}
+
 gboolean
 _dbus_gvalue_utils_test (const char *datadir)
 {
@@ -911,6 +961,62 @@ _dbus_gvalue_utils_test (const char *datadir)
     g_value_unset (&val);
   }
 
+  type = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
+  g_assert (dbus_g_type_is_map (type));
+  g_assert (dbus_g_type_get_map_key_specialization (type) == G_TYPE_STRING);
+  g_assert (dbus_g_type_get_map_value_specialization (type) == G_TYPE_VALUE);
+  {
+    GHashTable *instance;
+    GValue val = { 0, };
+    TestSpecializedHashData hashdata;
+    DBusGTypeSpecializedAppendContext ctx;
+    GValue *eltval;
+
+    instance = dbus_g_type_specialized_construct (type);
+    g_value_init (&val, type);
+    g_value_set_boxed_take_ownership (&val, instance);
+
+    dbus_g_type_specialized_init_append (&val, &ctx);
+
+    {
+      GValue keyval = { 0, };
+      GValue valval = { 0, };
+      g_value_init (&keyval, G_TYPE_STRING);
+      g_value_set_string (&keyval, "foo"); 
+
+      g_value_init (&valval, G_TYPE_VALUE);
+      eltval = g_new0 (GValue, 1);
+      g_value_init (eltval, G_TYPE_UINT);
+      g_value_set_uint (eltval, 20);
+      g_value_set_boxed_take_ownership (&valval, eltval);
+      dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
+    }
+
+    {
+      GValue keyval = { 0, };
+      GValue valval = { 0, };
+      g_value_init (&keyval, G_TYPE_STRING);
+      g_value_set_string (&keyval, "baz"); 
+      g_value_init (&valval, G_TYPE_VALUE);
+      eltval = g_new0 (GValue, 1);
+      g_value_init (eltval, G_TYPE_STRING);
+      g_value_set_string (eltval, "bar");
+      g_value_set_boxed_take_ownership (&valval, eltval);
+      dbus_g_type_specialized_map_append (&ctx, &keyval, &valval);
+    }
+
+    hashdata.seen_foo = FALSE;
+    hashdata.seen_baz = FALSE;
+    dbus_g_type_map_value_iterate (&val,
+                                  test_specialized_hash_2, 
+                                  &hashdata);
+    
+    g_assert (hashdata.seen_foo);
+    g_assert (hashdata.seen_baz);
+
+    g_value_unset (&val);
+  }
+
   type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING);
   g_assert (dbus_g_type_is_collection (type));
   g_assert (dbus_g_type_get_collection_specialization (type) == G_TYPE_STRING);
@@ -927,7 +1033,7 @@ _dbus_gvalue_utils_test (const char *datadir)
     g_value_init (&val, type);
     g_value_set_boxed_take_ownership (&val, instance);
 
-    dbus_g_type_specialized_collection_init_append (&val, &ctx);
+    dbus_g_type_specialized_init_append (&val, &ctx);
 
     g_value_init (&eltval, G_TYPE_STRING);
     g_value_set_static_string (&eltval, "foo");
index 4e7495c719d45f92dd9643f72974f1b03bc84d72..88397731f00f795fab72935d0db2c855c55d41d8 100644 (file)
@@ -22,6 +22,8 @@
  *
  */
 
+#include "config.h"
+#include "dbus-gtest.h"
 #include "dbus-gvalue.h"
 #include "dbus-gobject.h"
 #include "dbus-gvalue-utils.h"
@@ -76,12 +78,6 @@ static gboolean demarshal_variant               (DBusGValueMarshalCtx      *cont
                                                 DBusMessageIter           *iter,
                                                 GValue                    *value,
                                                 GError                   **error);
-static gboolean marshal_garray_basic            (DBusMessageIter           *iter,
-                                                const GValue              *value);
-static gboolean demarshal_garray_basic          (DBusGValueMarshalCtx      *context,
-                                                DBusMessageIter           *iter,
-                                                GValue                    *value,
-                                                GError                   **error);
 static gboolean marshal_proxy                   (DBusMessageIter           *iter,
                                                 const GValue             *value);
 static gboolean demarshal_proxy                 (DBusGValueMarshalCtx      *context,
@@ -102,17 +98,29 @@ static gboolean demarshal_object                (DBusGValueMarshalCtx      *cont
                                                 GError                   **error);
 static gboolean marshal_map                     (DBusMessageIter           *iter,
                                                 const GValue              *value);
-static gboolean demarshal_ghashtable            (DBusGValueMarshalCtx      *context,
+static gboolean demarshal_map                   (DBusGValueMarshalCtx      *context,
                                                 DBusMessageIter           *iter,
                                                 GValue                    *value,
                                                 GError                   **error);
 
 static gboolean marshal_collection              (DBusMessageIter           *iter,
                                                 const GValue              *value);
+static gboolean marshal_collection_ptrarray     (DBusMessageIter           *iter,
+                                                const GValue              *value);
+static gboolean marshal_collection_array        (DBusMessageIter           *iter,
+                                                const GValue              *value);
 static gboolean demarshal_collection            (DBusGValueMarshalCtx      *context,
                                                 DBusMessageIter           *iter,
                                                 GValue                    *value,
                                                 GError                   **error);
+static gboolean demarshal_collection_ptrarray   (DBusGValueMarshalCtx      *context,
+                                                DBusMessageIter           *iter,
+                                                GValue                    *value,
+                                                GError                   **error);
+static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *context,
+                                                DBusMessageIter           *iter,
+                                                GValue                    *value,
+                                                GError                   **error);
 
 static gboolean marshal_recurse                 (DBusMessageIter           *iter,
                                                 const GValue              *value);
@@ -198,30 +206,6 @@ register_basic (int typecode, const DBusGTypeMarshalData *typedata)
   set_type_metadata (basic_typecode_to_gtype (typecode), typedata);
 }
 
-static void
-register_array (int typecode, const DBusGTypeMarshalData *typedata)
-{
-  GType elt_gtype;
-  GType gtype;
-
-  elt_gtype = basic_typecode_to_gtype (typecode); 
-  gtype = dbus_g_type_get_collection ("GArray", elt_gtype);
-  set_type_metadata (gtype, typedata); 
-}
-
-static void
-register_dict (int key_type, int value_type, const DBusGTypeMarshalData *typedata)
-{
-  GType key_gtype;
-  GType value_gtype;
-  GType gtype;
-
-  key_gtype = basic_typecode_to_gtype (key_type); 
-  value_gtype = basic_typecode_to_gtype (value_type); 
-  gtype = dbus_g_type_get_map ("GHashTable", key_gtype, value_gtype);
-  set_type_metadata (gtype, typedata); 
-}
-
 void
 dbus_g_value_types_init (void)
 {
@@ -240,14 +224,6 @@ dbus_g_value_types_init (void)
     marshal_basic,
     demarshal_basic
   };
-  static const DBusGTypeMarshalVtable garray_basic_vtable = {
-    marshal_garray_basic,
-    demarshal_garray_basic
-  };
-  static const DBusGTypeMarshalVtable ghashtable_vtable = {
-    marshal_map,
-    demarshal_ghashtable
-  };
 
   /* Register basic types */
   {
@@ -374,56 +350,8 @@ dbus_g_value_types_init (void)
     set_type_metadata (G_TYPE_STRV, &typedata);
   };
 
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BOOLEAN_AS_STRING,
-      &garray_basic_vtable
-    };
-    register_array (DBUS_TYPE_BOOLEAN, &typedata);
-  }
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
-      &garray_basic_vtable
-    };
-    register_array (DBUS_TYPE_BYTE, &typedata);
-  }
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
-      &garray_basic_vtable
-    };
-    register_array (DBUS_TYPE_UINT32, &typedata);
-  }
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
-      &garray_basic_vtable
-    };
-    register_array (DBUS_TYPE_INT32, &typedata);
-  }
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_UINT64_AS_STRING,
-      &garray_basic_vtable
-    };
-    register_array (DBUS_TYPE_UINT64, &typedata);
-  }
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT64_AS_STRING,
-      &garray_basic_vtable
-    };
-    register_array (DBUS_TYPE_INT64, &typedata);
-  }
-  { 
-    static const DBusGTypeMarshalData typedata = {
-      DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
-      &ghashtable_vtable,
-    };
-    register_dict (DBUS_TYPE_STRING, DBUS_TYPE_STRING, &typedata);
-  }
 
+  /* Register some types specific to the D-BUS GLib bindings */
   {
     static const DBusGTypeMarshalVtable vtable = {
       marshal_proxy,
@@ -535,6 +463,7 @@ dbus_g_value_iterator_get_values (DBusGValueIterator *iter,
 
       context.gconnection = (iterval->value.recurse.toplevel)->value.toplevel.connection;
       context.proxy = (iterval->value.recurse.toplevel)->value.toplevel.proxy;
+
       if (!dbus_gvalue_demarshal (&context,
                                  &(iterval->value.recurse.iterator),
                                  value,
@@ -661,6 +590,10 @@ dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)
       DBusSignatureIter subiter;
 
       g_assert (dbus_type_is_container (current_type));
+
+      if (current_type == DBUS_TYPE_VARIANT)
+       return g_value_get_type ();
+      
       dbus_signature_iter_recurse (iter, &subiter);
 
       if (current_type == DBUS_TYPE_ARRAY)
@@ -673,8 +606,6 @@ dbus_gtype_from_signature_iter (DBusSignatureIter *iter, gboolean is_client)
        }
       else if (current_type == DBUS_TYPE_STRUCT)
        return signature_iter_to_g_type_struct (&subiter, is_client);
-      else if (current_type == DBUS_TYPE_VARIANT)
-       return g_value_get_type ();
       else if (current_type == DBUS_TYPE_DICT_ENTRY)
        return G_TYPE_INVALID;
       else
@@ -721,10 +652,6 @@ dbus_gtype_to_signature (GType gtype)
   char *ret;
   DBusGTypeMarshalData *typedata;
 
-  typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
-  if (typedata == NULL)
-    return NULL;
-
   if (dbus_g_type_is_collection (gtype))
     {
       GType elt_gtype;
@@ -751,7 +678,12 @@ dbus_gtype_to_signature (GType gtype)
       g_free (val_subsig);
     }
   else
-    ret = g_strdup (typedata->sig);
+    {
+      typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
+      if (typedata == NULL)
+       return NULL;
+      ret = g_strdup (typedata->sig);
+    }
   
   return ret;
 }
@@ -1066,53 +998,18 @@ demarshal_strv (DBusGValueMarshalCtx    *context,
 }
 
 static gboolean
-demarshal_garray_basic (DBusGValueMarshalCtx    *context,
-                       DBusMessageIter         *iter,
-                       GValue                  *value,
-                       GError                 **error)
-{
-  DBusMessageIter subiter;
-  GArray *ret;
-  GType elt_gtype;
-  int elt_size;
-  void *msgarray;
-  int msgarray_len;
-
-  dbus_message_iter_recurse (iter, &subiter);
-
-  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
-  g_assert (elt_gtype != G_TYPE_INVALID);
-  g_assert (dbus_g_type_is_fixed (elt_gtype));
-
-  elt_size = dbus_g_type_fixed_get_size (elt_gtype);
-  
-  ret = g_array_new (FALSE, TRUE, elt_size);
-
-  msgarray = NULL;
-  dbus_message_iter_get_fixed_array (&subiter,
-                                    &msgarray,
-                                    &msgarray_len);
-  g_assert (msgarray != NULL);
-  g_assert (msgarray_len >= 0);
-  g_array_append_vals (ret, msgarray, (guint) msgarray_len);
-
-  g_value_set_boxed_take_ownership (value, ret);
-  
-  return TRUE;
-}
-
-static gboolean
-demarshal_ghashtable (DBusGValueMarshalCtx    *context,
-                     DBusMessageIter         *iter,
-                     GValue                  *value,
-                     GError                 **error)
+demarshal_map (DBusGValueMarshalCtx    *context,
+              DBusMessageIter         *iter,
+              GValue                  *value,
+              GError                 **error)
 {
   GType gtype;
   DBusMessageIter subiter;
   int current_type;
-  GHashTable *ret;
+  gpointer ret;
   GType key_gtype;
   GType value_gtype;
+  DBusGTypeSpecializedAppendContext appendctx;
 
   current_type = dbus_message_iter_get_arg_type (iter);
   if (current_type != DBUS_TYPE_ARRAY)
@@ -1140,14 +1037,12 @@ demarshal_ghashtable (DBusGValueMarshalCtx    *context,
     }
 
   key_gtype = dbus_g_type_get_map_key_specialization (gtype);
-  g_assert (dbus_gtype_is_valid_hash_key (key_gtype));
   value_gtype = dbus_g_type_get_map_value_specialization (gtype);
-  g_assert (dbus_gtype_is_valid_hash_value (value_gtype));
 
-  ret = g_hash_table_new_full (dbus_g_hash_func_from_gtype (key_gtype),
-                              dbus_g_hash_equal_from_gtype (key_gtype),
-                              dbus_g_hash_free_from_gtype (key_gtype),
-                              dbus_g_hash_free_from_gtype (value_gtype));
+  ret = dbus_g_type_specialized_construct (gtype);
+  g_value_set_boxed_take_ownership (value, ret);
+
+  dbus_g_type_specialized_init_append (value, &appendctx);
 
   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
     {
@@ -1176,14 +1071,11 @@ demarshal_ghashtable (DBusGValueMarshalCtx    *context,
                                  error))
        return FALSE;
 
-      dbus_g_hash_table_insert_steal_values (ret,
-                                            &key_value,
-                                            &value_value);
-      /* Ownership of values passes to hash table, don't unset */
+      dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
+      /* Ownership of values passes to map, don't unset */
 
       dbus_message_iter_next (&subiter);
     }
-  g_value_set_boxed_take_ownership (value, ret);
   
   return TRUE;
 }
@@ -1200,6 +1092,8 @@ get_type_demarshaller (GType type)
        return demarshal_recurse;
       if (dbus_g_type_is_collection (type))
        return demarshal_collection;
+      if (dbus_g_type_is_map (type))
+       return demarshal_map;
 
       g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
       return NULL;
@@ -1216,6 +1110,24 @@ demarshal_collection (DBusGValueMarshalCtx    *context,
 {
   GType coltype;
   GType subtype;
+  
+  coltype = G_VALUE_TYPE (value);
+  subtype = dbus_g_type_get_collection_specialization (coltype);
+
+  if (dbus_g_type_is_fixed (subtype))
+    return demarshal_collection_array (context, iter, value, error);
+  else
+    return demarshal_collection_ptrarray (context, iter, value, error);
+}
+
+static gboolean
+demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
+                              DBusMessageIter         *iter,
+                              GValue                  *value,
+                              GError                 **error)
+{
+  GType coltype;
+  GType subtype;
   gpointer instance;
   DBusGTypeSpecializedAppendContext ctx;
   DBusGValueDemarshalFunc demarshaller;
@@ -1254,7 +1166,7 @@ demarshal_collection (DBusGValueMarshalCtx    *context,
   instance = dbus_g_type_specialized_construct (coltype);
   g_value_set_boxed_take_ownership (value, instance);
 
-  dbus_g_type_specialized_collection_init_append (value, &ctx);
+  dbus_g_type_specialized_init_append (value, &ctx);
 
   while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
     {
@@ -1277,6 +1189,42 @@ demarshal_collection (DBusGValueMarshalCtx    *context,
   return TRUE;
 }
 
+static gboolean
+demarshal_collection_array (DBusGValueMarshalCtx    *context,
+                           DBusMessageIter         *iter,
+                           GValue                  *value,
+                           GError                 **error)
+{
+  DBusMessageIter subiter;
+  GArray *ret;
+  GType elt_gtype;
+  int elt_size;
+  void *msgarray;
+  int msgarray_len;
+
+  dbus_message_iter_recurse (iter, &subiter);
+
+  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
+  g_assert (elt_gtype != G_TYPE_INVALID);
+  g_assert (dbus_g_type_is_fixed (elt_gtype));
+
+  elt_size = dbus_g_type_fixed_get_size (elt_gtype);
+  
+  ret = g_array_new (FALSE, TRUE, elt_size);
+
+  msgarray = NULL;
+  dbus_message_iter_get_fixed_array (&subiter,
+                                    &msgarray,
+                                    &msgarray_len);
+  g_assert (msgarray != NULL);
+  g_assert (msgarray_len >= 0);
+  g_array_append_vals (ret, msgarray, (guint) msgarray_len);
+
+  g_value_set_boxed_take_ownership (value, ret);
+  
+  return TRUE;
+}
+
 static gboolean
 demarshal_recurse (DBusGValueMarshalCtx    *context,
                   DBusMessageIter         *iter,
@@ -1544,50 +1492,6 @@ marshal_strv (DBusMessageIter   *iter,
   return ret;
 }
 
-static gboolean
-marshal_garray_basic (DBusMessageIter   *iter,
-                     const GValue      *value)
-{
-  GType elt_gtype;
-  DBusMessageIter subiter;
-  GArray *array;
-  guint elt_size;
-  char *subsignature_str;
-
-  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
-  /* FIXME - this means we can't send an array of DBusGValue right now... */
-  subsignature_str = dbus_gtype_to_signature (elt_gtype);
-  g_assert (subsignature_str != NULL);
-  
-  elt_size = dbus_g_type_fixed_get_size (elt_gtype);
-
-  array = g_value_get_boxed (value);
-
-  if (!dbus_message_iter_open_container (iter,
-                                        DBUS_TYPE_ARRAY,
-                                        subsignature_str,
-                                        &subiter))
-    goto oom;
-
-  /* TODO - This assumes that basic values are the same size
-   * is this always true?  If it is we can probably avoid
-   * a lot of the overhead in _marshal_basic_instance...
-   */
-  if (!dbus_message_iter_append_fixed_array (&subiter,
-                                            subsignature_str[0],
-                                            &(array->data),
-                                            array->len))
-    goto oom;
-
-  if (!dbus_message_iter_close_container (iter, &subiter))
-    goto oom;
-  g_free (subsignature_str);
-  return TRUE;
- oom:
-  g_error ("out of memory");
-  return FALSE;
-}
-
 static gboolean
 marshal_proxy (DBusMessageIter         *iter,
               const GValue            *value)
@@ -1791,6 +1695,8 @@ get_type_marshaller (GType type)
        return marshal_recurse;
       if (dbus_g_type_is_collection (type))
        return marshal_collection;
+      if (dbus_g_type_is_map (type))
+       return marshal_map;
 
       g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
       return NULL;
@@ -1822,6 +1728,22 @@ collection_marshal_iterator (const GValue *eltval,
 static gboolean
 marshal_collection (DBusMessageIter         *iter,
                    const GValue            *value)
+{
+  GType coltype;
+  GType subtype;
+  
+  coltype = G_VALUE_TYPE (value);
+  subtype = dbus_g_type_get_collection_specialization (coltype);
+
+  if (dbus_g_type_is_fixed (subtype))
+    return marshal_collection_array (iter, value);
+  else
+    return marshal_collection_ptrarray (iter, value);
+}
+
+static gboolean
+marshal_collection_ptrarray (DBusMessageIter         *iter,
+                            const GValue            *value)
 {
   GType coltype;
   GType elt_gtype;
@@ -1861,6 +1783,51 @@ marshal_collection (DBusMessageIter         *iter,
   return FALSE;
 }
 
+
+static gboolean
+marshal_collection_array (DBusMessageIter   *iter,
+                         const GValue      *value)
+{
+  GType elt_gtype;
+  DBusMessageIter subiter;
+  GArray *array;
+  guint elt_size;
+  char *subsignature_str;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
+  g_assert (dbus_g_type_is_fixed (elt_gtype));
+  subsignature_str = dbus_gtype_to_signature (elt_gtype);
+  g_assert (subsignature_str != NULL);
+  
+  elt_size = dbus_g_type_fixed_get_size (elt_gtype);
+
+  array = g_value_get_boxed (value);
+
+  if (!dbus_message_iter_open_container (iter,
+                                        DBUS_TYPE_ARRAY,
+                                        subsignature_str,
+                                        &subiter))
+    goto oom;
+
+  /* TODO - This assumes that basic values are the same size
+   * is this always true?  If it is we can probably avoid
+   * a lot of the overhead in _marshal_basic_instance...
+   */
+  if (!dbus_message_iter_append_fixed_array (&subiter,
+                                            subsignature_str[0],
+                                            &(array->data),
+                                            array->len))
+    goto oom;
+
+  if (!dbus_message_iter_close_container (iter, &subiter))
+    goto oom;
+  g_free (subsignature_str);
+  return TRUE;
+ oom:
+  g_error ("out of memory");
+  return FALSE;
+}
+
 static gboolean
 marshal_recurse (DBusMessageIter         *iter,
                 const GValue            *value)
@@ -1882,3 +1849,54 @@ dbus_gvalue_marshal (DBusMessageIter         *iter,
     return FALSE;
   return marshaller (iter, value);
 }
+
+#ifdef DBUS_BUILD_TESTS
+
+static void
+assert_type_maps_to (GType gtype, const char *expected_sig)
+{
+  char *sig;
+  sig = dbus_gtype_to_signature (gtype);
+  g_assert (sig != NULL);
+  g_assert (!strcmp (expected_sig, sig));
+  g_free (sig);
+}
+
+static void
+assert_signature_maps_to (const char *sig, GType expected_gtype)
+{
+  g_assert (dbus_gtype_from_signature (sig, TRUE) == expected_gtype);
+}
+
+static void
+assert_bidirectional_mapping (GType gtype, const char *expected_sig)
+{
+  assert_type_maps_to (gtype, expected_sig);
+  assert_signature_maps_to (expected_sig, gtype);
+}
+
+/**
+ * @ingroup DBusGLibInternals
+ * Unit test for general glib stuff
+ * @returns #TRUE on success.
+ */
+gboolean
+_dbus_gvalue_test (const char *test_data_dir)
+{
+  dbus_g_value_types_init ();
+  
+  assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
+  assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
+  assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
+
+  assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                               DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
+  assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+                               DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
+  assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
+                               DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
index 54c630ffc05b7da23997f3c21374813a2e5be79c..88b21847d92096d3e984ff69ce1fe7df55668a88 100644 (file)
@@ -59,8 +59,9 @@ typedef struct
 {
   char *name;
   char *state;
+  gdouble progress;
   DBusGProxy *proxy;
-  DBusGProxyCall *get_initial_state_call;
+  DBusGProxyCall *get_progress_call;
 } MachineInfo;
 
 typedef struct
@@ -90,6 +91,15 @@ proxy_to_iter (GtkTreeModel *model, DBusGProxy *proxy, GtkTreeIter *iter)
   return FALSE;
 }
 
+static void
+signal_row_change (ClientState *state, GtkTreeIter *iter)
+{
+  GtkTreePath *path;
+  path = gtk_tree_model_get_path (state->store, iter);
+  gtk_tree_model_row_changed (state->store, path, iter);
+  gtk_tree_path_free (path);
+}
+
 static void
 get_machine_info_cb (DBusGProxy *proxy,
                     DBusGProxyCall *call,
@@ -115,13 +125,67 @@ get_machine_info_cb (DBusGProxy *proxy,
   info->name = name;
   g_free (info->state);
   info->state = statename;
-  {
-    GtkTreePath *path;
-    path = gtk_tree_model_get_path (state->store, &iter);
-    gtk_tree_model_row_changed (state->store, path, &iter);
-    gtk_tree_path_free (path);
-  }
-  info->get_initial_state_call = NULL;
+  signal_row_change (state, &iter);
+}
+
+static void
+set_proxy_acquisition_progress (ClientState *state,
+                               DBusGProxy *proxy,
+                               double progress)
+{
+  MachineInfo *info;
+  GtkTreeIter iter;
+
+  if (!proxy_to_iter (state->store, proxy, &iter))
+    g_assert_not_reached ();
+  gtk_tree_model_get (state->store, &iter, 0, &info, -1);
+
+  /* Ignore machines in unknown state */
+  if (!info->state)
+    return;
+  
+  if (strcmp (info->state, "Acquired"))
+    lose ("Got AcquisitionProgress signal in bad state %s",
+         info->state);
+
+  g_print ("Got acquisition progress change for %p (%s) to %f\n", proxy, info->name ? info->name : "(unknown)", progress);
+
+  info->progress = progress;
+
+  signal_row_change (state, &iter);
+}
+
+static void
+proxy_acquisition_changed_cb (DBusGProxy *proxy,
+                             double progress,
+                             gpointer user_data)
+{
+  set_proxy_acquisition_progress (user_data, proxy, progress);
+}
+
+static void
+get_acquiring_progress_cb (DBusGProxy *proxy,
+                          DBusGProxyCall *call,
+                          gpointer user_data)
+{
+  GError *error = NULL;
+  MachineInfo *info;
+  GtkTreeIter iter;
+  ClientState *state = user_data;
+  gdouble progress;
+
+  if (!proxy_to_iter (state->store, proxy, &iter))
+    g_assert_not_reached ();
+  gtk_tree_model_get (state->store, &iter, 0, &info, -1);
+
+  g_assert (info->get_progress_call == call);
+
+  if (!dbus_g_proxy_end_call (proxy, call, &error,
+                             G_TYPE_DOUBLE, &progress, G_TYPE_INVALID))
+    lose_gerror ("Failed to complete GetAcquiringProgress call", error);
+  info->get_progress_call = NULL;
+
+  set_proxy_acquisition_progress (state, proxy, progress);
 }
 
 static void
@@ -139,25 +203,27 @@ proxy_state_changed_cb (DBusGProxy *proxy,
 
   g_print ("Got state change for %p (%s) to %s\n", proxy, info->name ? info->name : "(unknown)", statename);
 
-  /* If we got a signal for the state, we shouldn't update
-   * based on the (possibly stale) call
-   */
-  if (info->get_initial_state_call != NULL)
-    {
-      g_print ("Cancelling outstanding GetInfo call for %p due to signal\n", proxy);
-      dbus_g_proxy_cancel_call (proxy, info->get_initial_state_call);
-      info->get_initial_state_call = NULL;
-    }
-
   g_free (info->state);
   info->state = g_strdup (statename);
 
-  {
-    GtkTreePath *path;
-    path = gtk_tree_model_get_path (state->store, &iter);
-    gtk_tree_model_row_changed (state->store, path, &iter);
-    gtk_tree_path_free (path);
-  }
+  if (!strcmp (info->state, "Acquired"))
+    {
+      g_print ("Starting GetAcquiringProgress call for %p\n", info->proxy);
+      if (info->get_progress_call != NULL)
+       {
+         dbus_g_proxy_cancel_call (info->proxy, info->get_progress_call);
+         info->get_progress_call = NULL;
+       }
+      info->get_progress_call = 
+       dbus_g_proxy_begin_call (info->proxy, "GetAcquiringProgress",
+                                get_acquiring_progress_cb,
+                                state, NULL,
+                                G_TYPE_INVALID);
+    }
+  else
+    info->progress = 0.0;
+
+  signal_row_change (state, &iter);
 }
 
 static void
@@ -172,6 +238,7 @@ add_machine (ClientState *state,
   info = g_new0 (MachineInfo, 1);
   info->name = g_strdup (name);
   info->state = g_strdup (mstate);
+  info->progress = 0.0;
 
   info->proxy = dbus_g_proxy_new_for_name (state->bus,
                                           "com.example.StateServer",
@@ -181,14 +248,11 @@ add_machine (ClientState *state,
   if (!info->state)
     {
       g_print ("Starting GetInfo call for %p\n", info->proxy);
-      info->get_initial_state_call
-       = dbus_g_proxy_begin_call (info->proxy, "GetInfo",
-                                  get_machine_info_cb,
-                                  state, NULL,
-                                  G_TYPE_INVALID);
+      dbus_g_proxy_begin_call (info->proxy, "GetInfo",
+                              get_machine_info_cb,
+                              state, NULL,
+                              G_TYPE_INVALID);
     }
-  else
-    info->get_initial_state_call = NULL;
 
   /* Watch for state changes */
   dbus_g_proxy_add_signal (info->proxy, "StateChanged",
@@ -200,6 +264,15 @@ add_machine (ClientState *state,
                               state,
                               NULL);
 
+  dbus_g_proxy_add_signal (info->proxy, "AcquisitionProgress",
+                          G_TYPE_DOUBLE, G_TYPE_INVALID);
+  
+  dbus_g_proxy_connect_signal (info->proxy,
+                              "AcquisitionProgress", 
+                              G_CALLBACK (proxy_acquisition_changed_cb),
+                              state,
+                              NULL);
+
   gtk_list_store_prepend (GTK_LIST_STORE (state->store), &iter);
   gtk_list_store_set (GTK_LIST_STORE (state->store), &iter, 0, info, -1);
 
@@ -306,6 +379,12 @@ do_a_state_change (ClientState *state)
       g_print ("Sending Start request to machine %s\n", info->name);
       dbus_g_proxy_call_no_reply (info->proxy, "Start", G_TYPE_INVALID);
     }
+  else if (!strcmp (info->state, "Loading"))
+    {
+      
+      g_print ("Sending Reacquire request to machine %s\n", info->name);
+      dbus_g_proxy_call_no_reply (info->proxy, "Reacquire", G_TYPE_INVALID);
+    }
   else
     {
       g_print ("Sending Shutdown request to machine %s\n", info->name);
@@ -318,7 +397,7 @@ do_something_random_2 (gpointer data)
 {
   ClientState *state = data;
   do_a_state_change (state);
-  g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state);
+  g_timeout_add (g_random_int_range (2000, 5000), do_something_random_2, state);
   return FALSE;
 }
 
@@ -328,12 +407,13 @@ do_something_random (gpointer data)
   ClientState *state = data;
   gint n_children;
 
-  switch (g_random_int_range (0, 2))
+  switch (g_random_int_range (0, 3))
     {
     case 0:
       send_create_machine (state);
       break;
     case 1:
+    case 2:
       do_a_state_change (state);
       break;
     default:
@@ -341,8 +421,11 @@ do_something_random (gpointer data)
     }
       
   n_children = gtk_tree_model_iter_n_children (state->store, NULL);
-  if (n_children >= 8)
-    g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state);
+  if (n_children >= 5)
+    {
+      g_print ("MAX children reached, switching to state changes only\n");
+      g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state);
+    }
   else
     g_timeout_add (g_random_int_range (500, 3000), do_something_random, state);
   return FALSE;
@@ -406,6 +489,34 @@ sort_by_state (GtkTreeModel *model,
                 info_b ? info_b->state : "");
 }
 
+static void 
+set_cell_progress (GtkTreeViewColumn *tree_column,
+                  GtkCellRenderer   *cell,
+                  GtkTreeModel      *tree_model,
+                  GtkTreeIter       *iter,
+                  gpointer           data)
+{
+  MachineInfo *info;
+  
+  gtk_tree_model_get (tree_model, iter, 0, &info, -1);
+  
+  g_object_set (cell, "value", (int) (info->progress * 100), NULL);
+}
+
+static gint
+sort_by_progress (GtkTreeModel *model,
+                 GtkTreeIter  *a,
+                 GtkTreeIter  *b,
+                 gpointer      user_data)
+{
+  MachineInfo *info_a, *info_b;
+
+  gtk_tree_model_get (model, a, 0, &info_a, -1);
+  gtk_tree_model_get (model, b, 0, &info_b, -1);
+
+  return info_a->progress > info_b->progress ? 1 : -1;
+}
+
 static void
 get_machines_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data)
 {
@@ -458,6 +569,17 @@ get_machines_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data)
                                   0, sort_by_state, NULL, NULL);
   gtk_tree_view_column_set_sort_column_id (col, 0);
   gtk_tree_view_append_column (GTK_TREE_VIEW (state->view), col);
+
+  rend = gtk_cell_renderer_progress_new ();
+  col = gtk_tree_view_column_new_with_attributes (_("Progress"), 
+                                                 rend, 
+                                                 NULL);
+  gtk_tree_view_column_set_cell_data_func (col, rend, set_cell_progress, NULL, NULL);
+  gtk_tree_view_column_set_resizable (col, TRUE);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (state->store), 
+                                  0, sort_by_progress, NULL, NULL);
+  gtk_tree_view_column_set_sort_column_id (col, 0);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (state->view), col);
   
   for (i = 0; i < objs->len; i++)
     {
index 7cadf1fe4d359e1529ed0354595189499cede935..2cbf39febc3943b0ab8dca49845ec2cedb0ebbbd 100644 (file)
@@ -104,6 +104,26 @@ sm_server_get_property (GObject *object,
     }
 }
 
+static void
+machine_state_changed_cb (SMObject *obj, const char *state, gpointer data)
+{
+  char *name;
+
+  g_object_get (obj, "name", &name, NULL);
+  g_print ("Machine %s switching to state %s\n", name, state);
+  g_free (name);
+}
+
+static void
+machine_acquisition_changed_cb (SMObject *obj, gdouble progress, gpointer data)
+{
+  char *name;
+
+  g_object_get (obj, "name", &name, NULL);
+  g_print ("Machine %s got progress %f\n", name, progress);
+  g_free (name);
+}
+
 gboolean
 sm_server_create_machine (SMServer *server, const char *name, GError **error)
 {
@@ -130,6 +150,13 @@ sm_server_create_machine (SMServer *server, const char *name, GError **error)
 
   g_print ("Created state machine with name %s at %s\n", name, path);
 
+  g_signal_connect_object (machine, "state-changed",
+                          G_CALLBACK (machine_state_changed_cb),
+                          NULL, 0);
+  g_signal_connect_object (machine, "acquisition-progress",
+                          G_CALLBACK (machine_acquisition_changed_cb),
+                          NULL, 0);
+
   g_signal_emit (server, sm_server_signals[MACHINE_CREATED], 0, name, path);
   
   return TRUE;
index 2bde0058799449ff4fae2c12e9954ac0b6173542..c94e2945c0c6cff1875ae44bd3aec8cc586f9055 100644 (file)
@@ -103,8 +103,8 @@ sm_object_state_get_type (void)
 
          ENUM_ENTRY (SM_OBJECT_STATE_SHUTDOWN, "Shutdown"),
          ENUM_ENTRY (SM_OBJECT_STATE_INITIALIZED, "Loading"),
-         ENUM_ENTRY (SM_OBJECT_STATE_ACQUIRED, "Resource acquired"),
-         ENUM_ENTRY (SM_OBJECT_STATE_OPERATING, "Operating normally"),
+         ENUM_ENTRY (SM_OBJECT_STATE_ACQUIRED, "Acquired"),
+         ENUM_ENTRY (SM_OBJECT_STATE_OPERATING, "Operating"),
          { 0, 0, 0 }
        };
 
@@ -175,6 +175,21 @@ sm_object_get_property (GObject *object,
     }
 }
 
+static const char *
+state_to_string (SMObjectState state)
+{
+  GEnumValue *value;
+  GEnumClass *prop_class;
+  const char *ret;
+  
+  prop_class = g_type_class_ref (SM_TYPE_OBJECT_STATE);
+  value = g_enum_get_value (prop_class, state);
+  ret = value->value_nick;
+
+  g_type_class_unref (prop_class);
+  return ret;
+}
+
 static void
 queue_task (SMObject *object, guint delay, GSourceFunc func)
 {
@@ -188,6 +203,8 @@ idle_state_change (gpointer data)
 {
   SMObject *object = data;
 
+  g_print ("doing idle state change for %s to %s\n",
+          object->name, state_to_string (object->requested_state));
   state_change (object, object->requested_state);
   return FALSE;
 }
@@ -197,7 +214,8 @@ idle_further_acquire (gpointer data)
 {
   SMObject *object = data;
 
-  object->acquisition_progress += g_random_double_range (0.05, 0.5);
+  g_print ("doing idle acquisition for machine %s\n", object->name);
+  object->acquisition_progress += g_random_double_range (0.20, 0.7);
   if (object->acquisition_progress > 1.0)
     {
       object->acquisition_progress = 1.0;
@@ -220,26 +238,10 @@ clear_pending_tasks (SMObject *object)
   object->pending_tasks = NULL;
 }
 
-static const char *
-state_to_string (SMObjectState state)
-{
-  GEnumValue *value;
-  GEnumClass *prop_class;
-  const char *ret;
-  
-  prop_class = g_type_class_ref (SM_TYPE_OBJECT_STATE);
-  value = g_enum_get_value (prop_class, state);
-  ret = value->value_nick;
-
-  g_type_class_unref (prop_class);
-  return ret;
-}
-
 static void
 state_change (SMObject *object, SMObjectState new_state)
 {
   g_signal_emit (object, sm_object_signals[STATE_CHANGED], 0,
-                state_to_string (object->state),
                 state_to_string (new_state));
 
   clear_pending_tasks (object);
@@ -288,7 +290,7 @@ sm_object_start (SMObject *object, GError **error)
 gboolean
 sm_object_shutdown (SMObject *object, GError **error)
 {
-  if (object->state != SM_OBJECT_STATE_INITIALIZED)
+  if (object->state == SM_OBJECT_STATE_SHUTDOWN)
     {
       g_set_error (error,
                   SM_ERROR,
@@ -321,7 +323,7 @@ sm_object_reinitialize (SMObject *object, GError **error)
 gboolean
 sm_object_reacquire (SMObject *object, GError **error)
 {
-  if (object->state != SM_OBJECT_STATE_ACQUIRED)
+  if (object->state == SM_OBJECT_STATE_ACQUIRED)
     {
       g_set_error (error,
                   SM_ERROR,
index 15cd769a0b9c7ddd2a41e306678625add9819d18..4fbe797ee95a6e1077e9bbeb9a7d06d940dee427 100644 (file)
@@ -26,6 +26,13 @@ static gboolean proxy_destroy_and_nameowner_complete = FALSE;
 static void lose (const char *fmt, ...) G_GNUC_NORETURN G_GNUC_PRINTF (1, 2);
 static void lose_gerror (const char *prefix, GError *error) G_GNUC_NORETURN;
 
+static void
+unset_and_free_gvalue (gpointer val)
+{
+  g_value_unset (val);
+  g_free (val);
+}
+
 static gboolean
 timed_exit (gpointer loop)
 {
@@ -40,6 +47,7 @@ proxy_destroyed_cb (DBusGProxy *proxy, gpointer user_data)
   proxy_destroyed = TRUE;
   if (proxy_destroy_and_nameowner && !proxy_destroy_and_nameowner_complete && await_terminating_service == NULL)
     {
+      g_source_remove (exit_timeout);
       g_main_loop_quit (loop);
       proxy_destroy_and_nameowner_complete = TRUE;
     } 
@@ -62,11 +70,13 @@ name_owner_changed (DBusGProxy *proxy,
       await_terminating_service = NULL;
       if (proxy_destroy_and_nameowner && !proxy_destroy_and_nameowner_complete && proxy_destroyed)
        {
+         g_source_remove (exit_timeout);
          g_main_loop_quit (loop);
          proxy_destroy_and_nameowner_complete = TRUE;
        } 
       else if (!proxy_destroy_and_nameowner)
        {
+         g_source_remove (exit_timeout);
          g_main_loop_quit (loop);
        }
     }
@@ -837,6 +847,50 @@ main (int argc, char **argv)
 
   run_mainloop ();
 
+  {
+    GValue *val;
+    GHashTable *table;
+    GHashTable *ret_table;
+
+    table = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                  g_free, unset_and_free_gvalue);
+    
+    val = g_new0 (GValue, 1);
+    g_value_init (val, G_TYPE_UINT);
+    g_value_set_uint (val, 42);
+    g_hash_table_insert (table, g_strdup ("foo"), val);
+
+    val = g_new0 (GValue, 1);
+    g_value_init (val, G_TYPE_STRING);
+    g_value_set_string (val, "hello");
+    g_hash_table_insert (table, g_strdup ("bar"), val);
+
+    ret_table = NULL;
+    g_print ("Calling ManyStringify\n");
+    if (!dbus_g_proxy_call (proxy, "ManyStringify", &error,
+                           dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), table,
+                           G_TYPE_INVALID,
+                           dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &ret_table,
+                           G_TYPE_INVALID))
+      lose_gerror ("Failed to complete ManyStringify call", error);
+
+    g_assert (ret_table != NULL);
+    g_assert (g_hash_table_size (ret_table) == 2);
+
+    val = g_hash_table_lookup (ret_table, "foo");
+    g_assert (val != NULL);
+    g_assert (G_VALUE_HOLDS_STRING (val));
+    g_assert (!strcmp ("42", g_value_get_string (val)));
+
+    val = g_hash_table_lookup (ret_table, "bar");
+    g_assert (val != NULL);
+    g_assert (G_VALUE_HOLDS_STRING (val));
+    g_assert (!strcmp ("hello", g_value_get_string (val)));
+
+    g_hash_table_destroy (table);
+    g_hash_table_destroy (ret_table);
+  }
+
   {
     guint val;
     char *ret_path;
@@ -1135,6 +1189,9 @@ main (int argc, char **argv)
     lose_gerror ("Failed to complete Uppercase call", error);
   g_free (v_STRING_2);
 
+  if (getenv ("DBUS_GLIB_TEST_SLEEP_AFTER_ACTIVATION1"))
+    g_usleep (8 * G_USEC_PER_SEC);
+
   dbus_g_proxy_add_signal (proxy, "Frobnicate", G_TYPE_INT, G_TYPE_INVALID);
   
   dbus_g_proxy_connect_signal (proxy, "Frobnicate",
@@ -1175,6 +1232,9 @@ main (int argc, char **argv)
                          G_TYPE_INVALID, G_TYPE_INVALID))
     lose_gerror ("Failed to complete EmitFrobnicate call", error);
 
+  if (getenv ("DBUS_GLIB_TEST_SLEEP_AFTER_ACTIVATION2"))
+    g_usleep (8 * G_USEC_PER_SEC);
+
   dbus_g_connection_flush (connection);
   exit_timeout = g_timeout_add (5000, timed_exit, loop);
   g_main_loop_run (loop);
index a9e5792682858e77f4e9521932d0818c1640de2e..580eb107a06e5863372cb810e84631a99730efca 100644 (file)
@@ -63,6 +63,8 @@ gboolean my_object_many_return (MyObject *obj, guint32 *arg0, char **arg1, gint3
 gboolean my_object_recursive1 (MyObject *obj, GArray *array, guint32 *len_ret, GError **error);
 gboolean my_object_recursive2 (MyObject *obj, guint32 reqlen, GArray **array, GError **error);
 
+gboolean my_object_many_stringify (MyObject *obj, GHashTable *vals, GHashTable **ret, GError **error);
+
 gboolean my_object_objpath (MyObject *obj, const char *in, char **arg1, GError **error);
 
 gboolean my_object_get_objs (MyObject *obj, GPtrArray **objs, GError **error);
@@ -397,6 +399,38 @@ my_object_many_uppercase (MyObject *obj, const char * const *in, char ***out, GE
   return TRUE;
 }
 
+static void
+hash_foreach_stringify (gpointer key, gpointer val, gpointer user_data)
+{
+  const char *keystr = key;
+  const GValue *value = val;
+  GValue *sval;
+  GHashTable *ret = user_data;
+
+  sval = g_new0 (GValue, 1);
+  g_value_init (sval, G_TYPE_STRING);
+  if (!g_value_transform (value, sval))
+    g_assert_not_reached ();
+
+  g_hash_table_insert (ret, g_strdup (keystr), sval);
+}
+
+static void
+unset_and_free_gvalue (gpointer val)
+{
+  g_value_unset (val);
+  g_free (val);
+}
+
+gboolean
+my_object_many_stringify (MyObject *obj, GHashTable /* char * -> GValue * */ *vals, GHashTable /* char * -> GValue * */ **ret, GError **error)
+{
+  *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
+                               g_free, unset_and_free_gvalue);
+  g_hash_table_foreach (vals, hash_foreach_stringify, *ret);
+  return TRUE;
+}
+
 gboolean
 my_object_objpath (MyObject *obj, const char *incoming, char **outgoing, GError **error)
 {
index 272f7b23f25b9e2dc3a40ac0a2cf904a004db0ac..c299a80cc0be7fbc6bdae5d813564174b65c49d9 100644 (file)
       <arg type="u" direction="out" />
     </method>
 
+    <method name="ManyStringify">
+      <arg type="a{sv}" direction="in"/>
+      <arg type="a{sv}" direction="out"/>
+    </method>
+
     <method name="EmitFrobnicate">
     </method>