2005-07-06 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Wed, 6 Jul 2005 21:27:53 +0000 (21:27 +0000)
committerColin Walters <walters@verbum.org>
Wed, 6 Jul 2005 21:27:53 +0000 (21:27 +0000)
* dbus/dbus-glib.h (DBusGPendingCall, DBusGPendingCallNotify)
(DBUS_TYPE_G_PENDING_CALL, dbus_g_pending_call_get_g_type)
(dbus_g_pending_call_ref, dbus_g_pending_call_unref): Delete.
(dbus_g_pending_call_set_notify, dbus_g_pending_call_cancel):
Delete in favor of dbus_g_proxy_begin_call and
dbus_g_proxy_cancel_call.
(DBusGProxyCall, DBusGProxyCallNotify): New.
(dbus_g_proxy_begin_call): Change prototype to take callback, user
data, and destroy function.  This replaces
dbus_g_pending_call_set_notify.
(dbus_g_proxy_cancel_call): Prototype.
(DBusGAsyncData): Delete, shouldn't be needed anymore.

* glib/dbus-gproxy.c (struct _DBusGProxy): Add call_id_counter and
pending_calls map.
(struct _DBusGProxyManager): Add bus_proxy member, which is an
internal proxy for calls to the bus. Remove
pending_nameowner_calls, now the internal proxy keeps track.
(dbus_g_proxy_manager_unref): Unref bus proxy, remove reference to
pending_nameowner_calls.
(got_name_owner_cb): Update prototype, and use
dbus_g_proxy_end_call.
(got_name_owner_cb): Remove reference to pending_nameowner_calls.
(dbus_g_proxy_manager_register): Delete directly libdbus code in
favor of using internal proxy.
(dbus_g_proxy_manager_unregister): Update to use
dbus_g_proxy_cancel_call for any pending GetNameOwner call.
(dbus_g_proxy_init): Initialize pending calls map.
(dbus_g_proxy_constructor): New.
(dbus_g_proxy_class_init): Add get/set property functions,
constructor, and add NAME, PATH, and INTERFACE properties.
(cancel_pending_call): New function.
(dbus_g_proxy_dispose): Iterate over any outstanding calls and
cancel them.
(dbus_g_proxy_set_property, dbus_g_proxy_get_property): New.
(GPendingNotifyClosure): New structure.
(d_pending_call_notify, d_pending_call_free): Moved here from
dbus-glib.c.
(DBUS_G_VALUE_ARRAY_COLLECT_ALL): Moved around to satisfy function
ordering.
(manager_begin_bus_call): New internal function for talking to
internal bus proxy.
(dbus_g_proxy_new): Construct object using GObjet properties.
(dbus_g_proxy_begin_call_internal): Update to take user data, etc.
Create closure of same, and insert call into map of pending calls.
(dbus_g_proxy_end_call_internal): Take call id instead of pending
call.  Look up pending call in current set.  Remove it when we've
completed.
(dbus_g_pending_call_end, dbus_g_proxy_end_call_internal): Delete.
(dbus_g_proxy_begin_call): Change API to take callback, user data,
and destroy function directly.
(dbus_g_proxy_end_call): Update to take DBusGProxyCall.
(dbus_g_proxy_call): Invoke with NULL callback.
(dbus_g_proxy_cancel_call): New function, replaces
dbus_g_pending_call_cancel.

* glib/dbus-gparser.c (validate_signature): Fix call to
dbus_set_g_error.

* glib/dbus-gobject.c (dbus_g_object_type_dbus_metadata_quark):
New quark for attaching metadata to GType.
(info_hash): Delete.
(lookup_object_info): Look up using quark.
(dbus_g_object_type_install_info): Check that a type is classed,
not that it's an object.  Also just install type data using quark
instead of using global hash.

* glib/dbus-glib.c (dbus_g_pending_call_ref)
(dbus_g_pending_call_unref, dbus_pending_call_get_g_type)
(GPendingNotifyClosure): Delete.
(d_pending_call_notify, d_pending_call_free): Move to dbus-gproxy.c.
(dbus_g_pending_call_set_notify, dbus_g_pending_call_cancel): Delete.

* glib/dbus-binding-tool-glib.c (generate_client_glue): Disable async
client method generation until we can fix it...

* tools/dbus-viewer.c (load_child_nodes): Use dbus_g_proxy_call.
(load_from_service_thread_func): Ditto.

* tools/dbus-names-model.c (struct NamesModel): Hold
DBusGProxyCall.
(have_names_notify): Update prototype, use
dbus_g_proxy_cancel_call.
(names_model_reload): Update for new dbus_g_proxy_begin_call API.

* tools/dbus-monitor.c (filter_func): Update for print_message
API change.

* test/glib/test-dbus-glib.c: Add more tests for async
invocations.  Update many begin_call/end_call pairs to just use
dbus_g_proxy_call.

* tools/dbus-send.c (main): Add --print-reply=literal mode.  This
allows us to dump print-introspect.c.

* tools/dbus-print-message.h (print_message): Add literal argument
to print_message which is intended to allow printing arguments without
metadata like "string=".

* tools/dbus-print-message.c (print_iter): Add literal argument.
(print_message): Allow printing string messages literally.

15 files changed:
ChangeLog
dbus/dbus-glib.h
glib/dbus-binding-tool-glib.c
glib/dbus-glib.c
glib/dbus-gobject.c
glib/dbus-gparser.c
glib/dbus-gproxy.c
test/glib/test-dbus-glib.c
tools/dbus-monitor.c
tools/dbus-names-model.c
tools/dbus-print-message.c
tools/dbus-print-message.h
tools/dbus-send.c
tools/dbus-viewer.c
tools/print-introspect.c

index 4bd4924..f7320f9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,107 @@
+2005-07-06  Colin Walters  <walters@verbum.org>
+
+       * dbus/dbus-glib.h (DBusGPendingCall, DBusGPendingCallNotify)
+       (DBUS_TYPE_G_PENDING_CALL, dbus_g_pending_call_get_g_type)
+       (dbus_g_pending_call_ref, dbus_g_pending_call_unref): Delete.
+       (dbus_g_pending_call_set_notify, dbus_g_pending_call_cancel):
+       Delete in favor of dbus_g_proxy_begin_call and
+       dbus_g_proxy_cancel_call.
+       (DBusGProxyCall, DBusGProxyCallNotify): New.
+       (dbus_g_proxy_begin_call): Change prototype to take callback, user
+       data, and destroy function.  This replaces
+       dbus_g_pending_call_set_notify.
+       (dbus_g_proxy_cancel_call): Prototype.
+       (DBusGAsyncData): Delete, shouldn't be needed anymore.
+
+       * glib/dbus-gproxy.c (struct _DBusGProxy): Add call_id_counter and
+       pending_calls map.
+       (struct _DBusGProxyManager): Add bus_proxy member, which is an
+       internal proxy for calls to the bus. Remove
+       pending_nameowner_calls, now the internal proxy keeps track.
+       (dbus_g_proxy_manager_unref): Unref bus proxy, remove reference to
+       pending_nameowner_calls.
+       (got_name_owner_cb): Update prototype, and use
+       dbus_g_proxy_end_call.
+       (got_name_owner_cb): Remove reference to pending_nameowner_calls.
+       (dbus_g_proxy_manager_register): Delete directly libdbus code in
+       favor of using internal proxy.
+       (dbus_g_proxy_manager_unregister): Update to use
+       dbus_g_proxy_cancel_call for any pending GetNameOwner call.
+       (dbus_g_proxy_init): Initialize pending calls map.
+       (dbus_g_proxy_constructor): New.
+       (dbus_g_proxy_class_init): Add get/set property functions,
+       constructor, and add NAME, PATH, and INTERFACE properties.
+       (cancel_pending_call): New function.
+       (dbus_g_proxy_dispose): Iterate over any outstanding calls and
+       cancel them.
+       (dbus_g_proxy_set_property, dbus_g_proxy_get_property): New.
+       (GPendingNotifyClosure): New structure.
+       (d_pending_call_notify, d_pending_call_free): Moved here from
+       dbus-glib.c.
+       (DBUS_G_VALUE_ARRAY_COLLECT_ALL): Moved around to satisfy function
+       ordering.
+       (manager_begin_bus_call): New internal function for talking to
+       internal bus proxy.
+       (dbus_g_proxy_new): Construct object using GObjet properties.
+       (dbus_g_proxy_begin_call_internal): Update to take user data, etc.
+       Create closure of same, and insert call into map of pending calls.
+       (dbus_g_proxy_end_call_internal): Take call id instead of pending
+       call.  Look up pending call in current set.  Remove it when we've
+       completed.
+       (dbus_g_pending_call_end, dbus_g_proxy_end_call_internal): Delete.
+       (dbus_g_proxy_begin_call): Change API to take callback, user data,
+       and destroy function directly.
+       (dbus_g_proxy_end_call): Update to take DBusGProxyCall.
+       (dbus_g_proxy_call): Invoke with NULL callback.
+       (dbus_g_proxy_cancel_call): New function, replaces
+       dbus_g_pending_call_cancel.
+
+       * glib/dbus-gparser.c (validate_signature): Fix call to
+       dbus_set_g_error.
+
+       * glib/dbus-gobject.c (dbus_g_object_type_dbus_metadata_quark):
+       New quark for attaching metadata to GType.
+       (info_hash): Delete.
+       (lookup_object_info): Look up using quark.
+       (dbus_g_object_type_install_info): Check that a type is classed,
+       not that it's an object.  Also just install type data using quark
+       instead of using global hash.
+
+       * glib/dbus-glib.c (dbus_g_pending_call_ref) 
+       (dbus_g_pending_call_unref, dbus_pending_call_get_g_type)
+       (GPendingNotifyClosure): Delete.
+       (d_pending_call_notify, d_pending_call_free): Move to dbus-gproxy.c.
+       (dbus_g_pending_call_set_notify, dbus_g_pending_call_cancel): Delete.
+
+       * glib/dbus-binding-tool-glib.c (generate_client_glue): Disable async
+       client method generation until we can fix it...
+       
+       * tools/dbus-viewer.c (load_child_nodes): Use dbus_g_proxy_call.
+       (load_from_service_thread_func): Ditto.
+
+       * tools/dbus-names-model.c (struct NamesModel): Hold
+       DBusGProxyCall.
+       (have_names_notify): Update prototype, use
+       dbus_g_proxy_cancel_call.
+       (names_model_reload): Update for new dbus_g_proxy_begin_call API.
+
+       * tools/dbus-monitor.c (filter_func): Update for print_message
+       API change.
+
+       * test/glib/test-dbus-glib.c: Add more tests for async
+       invocations.  Update many begin_call/end_call pairs to just use
+       dbus_g_proxy_call.
+
+       * tools/dbus-send.c (main): Add --print-reply=literal mode.  This
+       allows us to dump print-introspect.c.
+
+       * tools/dbus-print-message.h (print_message): Add literal argument
+       to print_message which is intended to allow printing arguments without
+       metadata like "string=".
+
+       * tools/dbus-print-message.c (print_iter): Add literal argument.
+       (print_message): Allow printing string messages literally.
+
 2005-07-05  Colin Walters  <walters@verbum.org>
 
        * glib/dbus-gproxy.c (marshal_dbus_message_to_g_marshaller):
index 41b3d9c..4b3672c 100644 (file)
@@ -40,39 +40,21 @@ typedef struct _DBusGConnection DBusGConnection;
  * Convert to DBusMessage with dbus_g_message_get_message() in dbus-glib-lowlevel.h
  */
 typedef struct _DBusGMessage DBusGMessage;
-/**
- * Deliberately not possible to convert to DBusPendingCall
- */
-typedef struct _DBusGPendingCall DBusGPendingCall;
-
-typedef void (* DBusGPendingCallNotify) (DBusGPendingCall *pending,
-                                         void             *user_data);
 
 
 #define DBUS_TYPE_G_CONNECTION   (dbus_g_connection_get_g_type ())
 #define DBUS_TYPE_G_MESSAGE      (dbus_g_message_get_g_type ())
-#define DBUS_TYPE_G_PENDING_CALL (dbus_g_message_get_g_type ())
 GType dbus_g_connection_get_g_type   (void) G_GNUC_CONST;
 GType dbus_g_message_get_g_type      (void) G_GNUC_CONST;
-GType dbus_g_pending_call_get_g_type (void) G_GNUC_CONST;
 
 
 DBusGConnection*  dbus_g_connection_ref          (DBusGConnection        *connection);
 void              dbus_g_connection_unref        (DBusGConnection        *connection);
-DBusGPendingCall* dbus_g_pending_call_ref        (DBusGPendingCall       *call);
-void              dbus_g_pending_call_unref      (DBusGPendingCall       *call);
 DBusGMessage*     dbus_g_message_ref             (DBusGMessage           *message);
 void              dbus_g_message_unref           (DBusGMessage           *message);
 
 void              dbus_g_connection_flush        (DBusGConnection        *connection);
 
-void              dbus_g_pending_call_set_notify (DBusGPendingCall       *call,
-                                                  DBusGPendingCallNotify  callback,
-                                                  void                   *callback_data,
-                                                  GDestroyNotify          free_data_func);
-void              dbus_g_pending_call_cancel     (DBusGPendingCall       *call);
-
-
 GQuark dbus_g_error_quark (void);
 #define DBUS_GERROR dbus_g_error_quark ()
 
@@ -221,6 +203,11 @@ typedef struct _DBusGProxyClass  DBusGProxyClass;
 #define DBUS_G_PROXY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TYPE_G_PROXY, DBusGProxyClass))
 
 
+typedef struct _DBusGProxyCall DBusGProxyCall;
+typedef void (* DBusGProxyCallNotify) (DBusGProxy       *proxy,
+                                      DBusGProxyCall   *call_id,
+                                      void             *user_data);
+
 GType             dbus_g_proxy_get_type              (void) G_GNUC_CONST;
 DBusGProxy*       dbus_g_proxy_new_for_name          (DBusGConnection   *connection,
                                                       const char        *name,
@@ -266,15 +253,20 @@ void              dbus_g_proxy_call_no_reply         (DBusGProxy        *proxy,
                                                       GType              first_arg_type,
                                                       ...);
 
-DBusGPendingCall* dbus_g_proxy_begin_call            (DBusGProxy        *proxy,
+DBusGProxyCall *  dbus_g_proxy_begin_call            (DBusGProxy        *proxy,
                                                       const char        *method,
+                                                     DBusGProxyCallNotify notify,
+                                                     gpointer           data,
+                                                     GDestroyNotify     destroy,
                                                       GType              first_arg_type,
                                                       ...);
 gboolean          dbus_g_proxy_end_call              (DBusGProxy        *proxy,
-                                                      DBusGPendingCall  *pending,
+                                                      DBusGProxyCall    *call,
                                                       GError           **error,
                                                       GType              first_arg_type,
                                                       ...);
+void              dbus_g_proxy_cancel_call           (DBusGProxy        *proxy,
+                                                      DBusGProxyCall    *call);
 
 const char*       dbus_g_proxy_get_path              (DBusGProxy        *proxy);
 
@@ -288,12 +280,6 @@ void              dbus_g_method_return               (DBusGMethodInvocation *con
 
 void              dbus_g_method_return_error         (DBusGMethodInvocation *context, GError *error);
 
-typedef struct {
-  DBusGProxy *proxy;
-  gpointer cb;
-  gpointer userdata;
-} DBusGAsyncData;
-
 #undef DBUS_INSIDE_DBUS_GLIB_H
 
 G_END_DECLS
index 4a33176..18ce1fc 100644 (file)
@@ -1350,7 +1350,9 @@ generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error
 
          WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n\n");
 
+#if 0
          write_async_method_client (channel, interface, method, error);
+#endif
        }
 
       if (!write_printf_to_iochannel ("#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_%s */\n\n", channel, error, iface_prefix))
index 5b30ce7..5dbcdf0 100644 (file)
@@ -112,30 +112,6 @@ dbus_g_message_unref (DBusGMessage *gmessage)
 }
 
 /**
- * Increments refcount on a pending call.
- *
- * @param call the call
- * @returns the same call
- */
-DBusGPendingCall*
-dbus_g_pending_call_ref (DBusGPendingCall  *call)
-{
-  dbus_pending_call_ref (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call));
-  return call;
-}
-
-/**
- * Decrements refcount on a pending call.
- *
- * @param call the call
- */
-void
-dbus_g_pending_call_unref (DBusGPendingCall  *call)
-{
-  dbus_pending_call_unref (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call));
-}
-
-/**
  * The implementation of DBUS_GERROR error domain. See documentation
  * for GError in GLib reference manual.
  *
@@ -235,24 +211,6 @@ dbus_message_get_g_type (void)
 }
 
 /**
- * Get the GLib type ID for a DBusPendingCall boxed type.
- *
- * @returns GLib type
- */
-GType
-dbus_pending_call_get_g_type (void)
-{
-  static GType our_type = 0;
-  
-  if (our_type == 0)
-    our_type = g_boxed_type_register_static ("DBusPendingCall",
-                                             (GBoxedCopyFunc) dbus_pending_call_ref,
-                                             (GBoxedFreeFunc) dbus_pending_call_unref);
-
-  return our_type;
-}
-
-/**
  * Get the GLib type ID for a DBusGConnection boxed type.
  *
  * @returns GLib type
@@ -289,24 +247,6 @@ dbus_g_message_get_g_type (void)
 }
 
 /**
- * Get the GLib type ID for a DBusGPendingCall boxed type.
- *
- * @returns GLib type
- */
-GType
-dbus_g_pending_call_get_g_type (void)
-{
-  static GType our_type = 0;
-  
-  if (our_type == 0)
-    our_type = g_boxed_type_register_static ("DBusGPendingCall",
-                                             (GBoxedCopyFunc) dbus_g_pending_call_ref,
-                                             (GBoxedFreeFunc) dbus_g_pending_call_unref);
-
-  return our_type;
-}
-
-/**
  * Get the DBusConnection corresponding to this DBusGConnection.
  * The return value does not have its refcount incremented.
  *
@@ -330,86 +270,6 @@ dbus_g_message_get_message (DBusGMessage *gmessage)
   return DBUS_MESSAGE_FROM_G_MESSAGE (gmessage);
 }
 
-typedef struct
-{
-  DBusGPendingCallNotify func;
-  void *data;
-  GDestroyNotify free_data_func;
-} GPendingNotifyClosure;
-
-static void
-d_pending_call_notify (DBusPendingCall *dcall,
-                       void            *data)
-{
-  GPendingNotifyClosure *closure = data;
-  DBusGPendingCall *gcall = DBUS_G_PENDING_CALL_FROM_PENDING_CALL (dcall);
-
-  (* closure->func) (gcall, closure->data);
-}
-
-static void
-d_pending_call_free (void *data)
-{
-  GPendingNotifyClosure *closure = data;
-  
-  if (closure->free_data_func)
-    (* closure->free_data_func) (closure->data);
-
-  g_free (closure);
-}
-  
-/**
- * Sets up a notification to be invoked when the pending call
- * is ready to be ended without blocking.
- * You can call dbus_g_proxy_end_call() at any time,
- * but it will block if no reply or error has been received yet.
- * This function lets you handle the reply asynchronously.
- *
- * @param call the pending call
- * @param callback the callback
- * @param callback_data data for the callback
- * @param free_data_func free the callback data with this
- */
-void
-dbus_g_pending_call_set_notify (DBusGPendingCall      *call,
-                                DBusGPendingCallNotify callback,
-                                void                  *callback_data,
-                                GDestroyNotify         free_data_func)
-{
-  GPendingNotifyClosure *closure;
-  DBusPendingCall *dcall;
-
-  g_return_if_fail (callback != NULL);
-  
-  closure = g_new (GPendingNotifyClosure, 1);
-
-  closure->func = callback;
-  closure->data = callback_data;
-  closure->free_data_func = free_data_func;
-
-  dcall = DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call);
-  dbus_pending_call_set_notify (dcall, d_pending_call_notify,
-                                closure,
-                                d_pending_call_free);
-}
-
-/**
- * Cancels a pending call. Does not affect the reference count
- * of the call, but it means you will never be notified of call
- * completion, and can't call dbus_g_proxy_end_call().
- *
- * @param call the call
- */
-void
-dbus_g_pending_call_cancel (DBusGPendingCall *call)
-{
-  DBusPendingCall *dcall;
-  
-  dcall = DBUS_PENDING_CALL_FROM_G_PENDING_CALL (call);
-
-  dbus_pending_call_cancel (dcall);
-}
-
 /** @} */ /* end of public API */
 
 
index c91f185..ed1f81c 100644 (file)
@@ -46,7 +46,6 @@ typedef struct
 } DBusGErrorInfo;
 
 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
-static GHashTable *info_hash = NULL;
 static GHashTable *marshal_table = NULL;
 static GData *error_metadata = NULL;
 
@@ -222,6 +221,16 @@ propsig_iterate (const char *data, const char **iface, const char **name)
   return string_table_next (data);
 }
 
+static GQuark
+dbus_g_object_type_dbus_metadata_quark (void)
+{
+  static GQuark quark;
+
+  if (!quark)
+    quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
+  return quark;
+}
+
 static const DBusGObjectInfo *
 lookup_object_info (GObject *object)
 {
@@ -230,16 +239,11 @@ lookup_object_info (GObject *object)
   
   ret = NULL;
   
-  g_static_rw_lock_reader_lock (&globals_lock);
-
-  if (info_hash == NULL)
-    goto out;
-
   for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
     {
       const DBusGObjectInfo *info;
 
-      info = g_hash_table_lookup (info_hash, g_type_class_peek (classtype));
+      info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ()); 
 
       if (info != NULL && info->format_version == 0)
        {
@@ -248,9 +252,6 @@ lookup_object_info (GObject *object)
        }
     }
 
- out:
-  g_static_rw_lock_reader_unlock (&globals_lock);
-
   return ret;
 }
 
@@ -1355,28 +1356,13 @@ void
 dbus_g_object_type_install_info (GType                  object_type,
                                 const DBusGObjectInfo *info)
 {
-  GObjectClass *object_class;
-
-  g_return_if_fail (G_TYPE_IS_OBJECT (object_type));
+  g_return_if_fail (G_TYPE_IS_CLASSED (object_type));
 
   dbus_g_value_types_init ();
 
-  object_class = g_type_class_ref (object_type);
-
-  g_return_if_fail (G_IS_OBJECT_CLASS (object_class));
-
-  g_static_rw_lock_writer_lock (&globals_lock);
-
-  if (info_hash == NULL)
-    {
-      info_hash = g_hash_table_new (NULL, NULL); /* direct hash */
-    }
-
-  g_hash_table_replace (info_hash, object_class, (void*) info);
-
-  g_static_rw_lock_writer_unlock (&globals_lock);
-
-  g_type_class_unref (object_class);
+  g_type_set_qdata (object_type,
+                   dbus_g_object_type_dbus_metadata_quark (),
+                   (gpointer) info);
 }
 
 /**
index daf9bc8..4959383 100644 (file)
@@ -475,7 +475,7 @@ validate_signature (const char *str,
   
   if (!dbus_signature_validate (str, &derror))
     {
-      dbus_set_g_error (&derror, error);
+      dbus_set_g_error (error, &derror);
       return FALSE;
     }
   return TRUE;
index 1a7292d..fd78b04 100644 (file)
@@ -32,6 +32,9 @@
 #include <glib/gi18n.h>
 #include <gobject/gvaluecollector.h>
 
+#define DBUS_G_PROXY_CALL_TO_ID(x) (GPOINTER_TO_UINT(x))
+#define DBUS_G_PROXY_ID_TO_CALL(x) (GUINT_TO_POINTER(x))
+
 /**
  * @addtogroup DBusGLibInternals
  *
@@ -56,11 +59,16 @@ struct _DBusGProxy
   char *path;                 /**< Path messages go to or NULL */
   char *interface;            /**< Interface messages go to or NULL */
 
-  DBusGPendingCall *name_call;/**< Pending call to retrieve name owner */
+  DBusGProxyCall *name_call;  /**< Pending call id to retrieve name owner */
   guint for_owner : 1;        /**< Whether or not this proxy is for a name owner */
   guint associated : 1;       /**< Whether or not this proxy is associated (for name proxies) */
 
+  /* FIXME: make threadsafe? */
+  guint call_id_counter;      /**< Integer counter for pending calls */
+
   GData *signal_signatures;   /**< D-BUS signatures for each signal */
+
+  GHashTable *pending_calls;  /**< Calls made on this proxy which have not yet returned */
 };
 
 /**
@@ -73,18 +81,42 @@ struct _DBusGProxyClass
 
 static void dbus_g_proxy_init               (DBusGProxy      *proxy);
 static void dbus_g_proxy_class_init         (DBusGProxyClass *klass);
+static GObject *dbus_g_proxy_constructor    (GType                  type,
+                                            guint                  n_construct_properties,
+                                            GObjectConstructParam *construct_properties);
+static void     dbus_g_proxy_set_property       (GObject               *object,
+                                                guint                  prop_id,
+                                                const GValue          *value,
+                                                GParamSpec            *pspec);
+static void     dbus_g_proxy_get_property       (GObject               *object,
+                                                guint                  prop_id,
+                                                GValue                *value,
+                                                GParamSpec            *pspec);
+
 static void dbus_g_proxy_finalize           (GObject         *object);
 static void dbus_g_proxy_dispose            (GObject         *object);
 static void dbus_g_proxy_destroy            (DBusGProxy      *proxy);
 static void dbus_g_proxy_emit_remote_signal (DBusGProxy      *proxy,
                                              DBusMessage     *message);
 
-static gboolean dbus_g_pending_call_end (DBusGConnection   *connection,
-                                        DBusGProxy        *proxycon,
-                                        DBusGPendingCall  *pending,
-                                        GError           **error,
-                                        GType              first_arg_type,
-                                        ...);
+static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager    *manager,
+                                              const char          *method,
+                                              DBusGProxyCallNotify notify,
+                                              gpointer             data,
+                                              GDestroyNotify       destroy,
+                                              GType                first_arg_type,
+                                              ...);
+static guint dbus_g_proxy_begin_call_internal (DBusGProxy          *proxy,
+                                              const char          *method,
+                                              DBusGProxyCallNotify notify,
+                                              gpointer             data,
+                                              GDestroyNotify       destroy,
+                                              GValueArray         *args);
+static gboolean dbus_g_proxy_end_call_internal (DBusGProxy        *proxy,
+                                               guint              call_id,
+                                               GError           **error,
+                                               GType              first_arg_type,
+                                               va_list            args);
 
 /**
  * A list of proxies with a given name+path+interface, used to
@@ -112,6 +144,8 @@ struct _DBusGProxyManager
   int refcount;      /**< Reference count */
   DBusConnection *connection; /**< Connection we're associated with. */
 
+  DBusGProxy *bus_proxy; /**< Special internal proxy used to talk to the bus */
+
   GHashTable *proxy_lists; /**< Hash used to route incoming signals
                             *   and iterate over proxies
                             */
@@ -119,9 +153,6 @@ struct _DBusGProxyManager
                            *   base name -> [name,name,...] for proxies which
                            *   are for names.
                            */
-  GSList *pending_nameowner_calls;  /**< List to keep track of pending
-                                    *   GetNameOwner calls
-                                    */
   GSList *unassociated_proxies;     /**< List of name proxies for which
                                     *   there was no result for
                                     *   GetNameOwner
@@ -168,7 +199,7 @@ dbus_g_proxy_manager_get (DBusConnection *connection)
 
   manager->refcount = 1;
   manager->connection = connection;
-  
+
   g_static_mutex_init (&manager->lock);
 
   /* Proxy managers keep the connection alive, which means that
@@ -215,6 +246,9 @@ dbus_g_proxy_manager_unref (DBusGProxyManager *manager)
     {
       UNLOCK_MANAGER (manager);
 
+      if (manager->bus_proxy)
+       g_object_unref (manager->bus_proxy);
+
       if (manager->proxy_lists)
         {
           /* can't have any proxies left since they hold
@@ -238,7 +272,6 @@ dbus_g_proxy_manager_unref (DBusGProxyManager *manager)
          manager->owner_names = NULL;
        }
 
-      g_assert (manager->pending_nameowner_calls == NULL);
       g_assert (manager->unassociated_proxies == NULL);
       
       g_static_mutex_free (&manager->lock);
@@ -723,13 +756,13 @@ dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager  *manager,
 }
 
 static void
-got_name_owner_cb (DBusGPendingCall *pending,
+got_name_owner_cb (DBusGProxy       *bus_proxy,
+                  DBusGProxyCall   *call,
                   void             *user_data)
 {
   DBusGProxy *proxy;
   GError *error;
   char *owner;
-  GSList *link;
 
   proxy = user_data;
   error = NULL;
@@ -737,15 +770,9 @@ got_name_owner_cb (DBusGPendingCall *pending,
 
   LOCK_MANAGER (proxy->manager);
 
-  link = g_slist_find (proxy->manager->pending_nameowner_calls, pending);
-  g_assert (link != NULL);
-  
-  if (!dbus_g_pending_call_end (DBUS_G_CONNECTION_FROM_CONNECTION (proxy->manager->connection),
-                               NULL,
-                               pending,
-                               &error,
-                               G_TYPE_STRING, &owner,
-                               G_TYPE_INVALID))
+  if (!dbus_g_proxy_end_call (bus_proxy, call, &error,
+                             G_TYPE_STRING, &owner,
+                             G_TYPE_INVALID))
     {
       if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
        {
@@ -767,7 +794,6 @@ got_name_owner_cb (DBusGPendingCall *pending,
 
  out:
   proxy->name_call = NULL;
-  proxy->manager->pending_nameowner_calls = g_slist_delete_link (proxy->manager->pending_nameowner_calls, link);
   UNLOCK_MANAGER (proxy->manager);
   g_free (owner);
 }
@@ -911,46 +937,14 @@ dbus_g_proxy_manager_register (DBusGProxyManager *manager,
 
       if (!dbus_g_proxy_manager_lookup_name_owner (manager, proxy->name, &info, &owner))
        {
-         DBusPendingCall *pending;
-         DBusGPendingCall *gpending;
-         DBusMessage *request, *reply;
-
-         g_assert (owner == NULL);
-  
-         reply = NULL;
-         
-         request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
-                                                 DBUS_PATH_DBUS,
-                                                 DBUS_INTERFACE_DBUS,
-                                                 "GetNameOwner");
-         if (request == NULL)
-           g_error ("Out of memory");
-         
-         if (!dbus_message_append_args (request, 
-                                        DBUS_TYPE_STRING, &(proxy->name), 
-                                        DBUS_TYPE_INVALID))
-           g_error ("Out of memory");
-
-         if (!dbus_connection_send_with_reply (manager->connection,
-                                               request,
-                                               &pending,
-                                               -1))
-           g_error ("Out of memory");
-         g_assert (pending != NULL);
-
-         gpending = DBUS_G_PENDING_CALL_FROM_PENDING_CALL (pending);
-
-         /* It's safe to keep a reference to proxy here;
-          * when the proxy is unreffed we cancel the call
-          */
-         dbus_g_pending_call_set_notify (gpending,
-                                         got_name_owner_cb,
-                                         proxy,
-                                         NULL);
+         proxy->name_call = manager_begin_bus_call (manager, "GetNameOwner",
+                                                    got_name_owner_cb,
+                                                    proxy, NULL,
+                                                    G_TYPE_STRING,
+                                                    proxy->name, 
+                                                    G_TYPE_INVALID);
          
          proxy->associated = FALSE;
-         proxy->name_call = gpending;
-         manager->pending_nameowner_calls = g_slist_prepend (manager->pending_nameowner_calls, gpending);
        }
       else
        {
@@ -1003,14 +997,10 @@ dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
        {
          GSList *link;
 
-         if (proxy->name_call != NULL)
+         if (proxy->name_call != 0)
            {
-             link = g_slist_find (manager->pending_nameowner_calls, proxy->name_call);
-             g_assert (link != NULL);
-         
-             dbus_g_pending_call_cancel (proxy->name_call);
-
-             manager->pending_nameowner_calls = g_slist_delete_link (manager->pending_nameowner_calls, link);
+             dbus_g_proxy_cancel_call (manager->bus_proxy, proxy->name_call);
+             proxy->name_call = 0;
            }
          else
            {
@@ -1022,7 +1012,7 @@ dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
        }
       else
        {
-         g_assert (proxy->name_call == NULL);
+         g_assert (proxy->name_call == 0);
          
          dbus_g_proxy_manager_unmonitor_name_owner (manager, proxy->name);
        }
@@ -1267,6 +1257,13 @@ marshal_dbus_message_to_g_marshaller (GClosure     *closure,
                                       const GValue *param_values,
                                       gpointer      invocation_hint,
                                       gpointer      marshal_data);
+enum
+{
+  PROP_0,
+  PROP_NAME,
+  PROP_PATH,
+  PROP_INTERFACE
+};
 
 enum
 {
@@ -1282,6 +1279,31 @@ static void
 dbus_g_proxy_init (DBusGProxy *proxy)
 {
   g_datalist_init (&proxy->signal_signatures);
+  proxy->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
+                                               (GDestroyNotify) dbus_pending_call_unref);
+}
+
+static GObject *
+dbus_g_proxy_constructor (GType                  type,
+                         guint                  n_construct_properties,
+                         GObjectConstructParam *construct_properties)
+{
+  DBusGProxy *proxy;
+  DBusGProxyClass *klass;
+  GObjectClass *parent_class;  
+
+  klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
+
+  parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+
+  proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
+                                                   construct_properties));
+
+  proxy->for_owner = (proxy->name[0] == ':');
+  proxy->name_call = 0;
+  proxy->associated = FALSE;
+
+  return G_OBJECT (proxy);
 }
 
 static void
@@ -1290,9 +1312,37 @@ dbus_g_proxy_class_init (DBusGProxyClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   
   parent_class = g_type_class_peek_parent (klass);
+
+  object_class->set_property = dbus_g_proxy_set_property;
+  object_class->get_property = dbus_g_proxy_get_property;
+
+  g_object_class_install_property (object_class,
+                                  PROP_NAME,
+                                  g_param_spec_string ("name",
+                                                       "name",
+                                                       "name",
+                                                       NULL,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class,
+                                  PROP_PATH,
+                                  g_param_spec_string ("path",
+                                                       "path",
+                                                       "path",
+                                                       NULL,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class,
+                                  PROP_INTERFACE,
+                                  g_param_spec_string ("interface",
+                                                       "interface",
+                                                       "interface",
+                                                       NULL,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
   
   object_class->finalize = dbus_g_proxy_finalize;
   object_class->dispose = dbus_g_proxy_dispose;
+  object_class->constructor = dbus_g_proxy_constructor;
   
   signals[DESTROY] =
     g_signal_new ("destroy",
@@ -1314,18 +1364,31 @@ dbus_g_proxy_class_init (DBusGProxyClass *klass)
 }
 
 static void
+cancel_pending_call (gpointer key, gpointer val, gpointer data)
+{
+  DBusGProxyCall *call = key;
+  DBusGProxy *proxy = data;
+
+  dbus_g_proxy_cancel_call (proxy, call);
+}
+
+static void
 dbus_g_proxy_dispose (GObject *object)
 {
   DBusGProxy *proxy;
 
   proxy = DBUS_G_PROXY (object);
 
-  if (proxy->manager)
+  /* Cancel outgoing pending calls */
+  g_hash_table_foreach (proxy->pending_calls, cancel_pending_call, proxy);
+  g_hash_table_destroy (proxy->pending_calls);
+
+  if (proxy->manager && proxy != proxy->manager->bus_proxy)
     {
       dbus_g_proxy_manager_unregister (proxy->manager, proxy);
       dbus_g_proxy_manager_unref (proxy->manager);
-      proxy->manager = NULL;
     }
+  proxy->manager = NULL;
   
   g_datalist_clear (&proxy->signal_signatures);
   
@@ -1359,6 +1422,56 @@ dbus_g_proxy_destroy (DBusGProxy *proxy)
   g_object_run_dispose (G_OBJECT (proxy));
 }
 
+static void
+dbus_g_proxy_set_property (GObject *object,
+                          guint prop_id,
+                          const GValue *value,
+                          GParamSpec *pspec)
+{
+  DBusGProxy *proxy = DBUS_G_PROXY (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      proxy->name = g_strdup (g_value_get_string (value));
+      break;
+    case PROP_PATH:
+      proxy->path = g_strdup (g_value_get_string (value));
+      break;
+    case PROP_INTERFACE:
+      proxy->interface = g_strdup (g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void 
+dbus_g_proxy_get_property (GObject *object,
+                          guint prop_id,
+                          GValue *value,
+                          GParamSpec *pspec)
+{
+  DBusGProxy *proxy = DBUS_G_PROXY (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      g_value_set_string (value, proxy->name);
+      break;
+    case PROP_PATH:
+      g_value_set_string (value, proxy->path);
+      break;
+    case PROP_INTERFACE:
+      g_value_set_string (value, proxy->interface);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
 /* this is to avoid people using g_signal_connect() directly,
  * to avoid confusion with local signal names, and because
  * of the horribly broken current setup (signals are added
@@ -1514,6 +1627,91 @@ dbus_g_proxy_emit_remote_signal (DBusGProxy  *proxy,
   goto out;
 }
 
+typedef struct
+{
+  DBusGProxy *proxy;
+  guint call_id;
+  DBusGProxyCallNotify func;
+  void *data;
+  GDestroyNotify free_data_func;
+} GPendingNotifyClosure;
+
+static void
+d_pending_call_notify (DBusPendingCall *dcall,
+                       void            *data)
+{
+  GPendingNotifyClosure *closure = data;
+
+  (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
+}
+
+static void
+d_pending_call_free (void *data)
+{
+  GPendingNotifyClosure *closure = data;
+  
+  if (closure->free_data_func)
+    (* closure->free_data_func) (closure->data);
+
+  g_free (closure);
+}
+  
+#define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
+do { \
+  GType valtype; \
+  int i = 0; \
+  VALARRAY = g_value_array_new (6); \
+  valtype = FIRST_ARG_TYPE; \
+  while (valtype != G_TYPE_INVALID) \
+    { \
+      const char *collect_err; \
+      GValue *val; \
+      g_value_array_append (VALARRAY, NULL); \
+      val = g_value_array_get_nth (VALARRAY, i); \
+      g_value_init (val, valtype); \
+      collect_err = NULL; \
+      G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
+      valtype = va_arg (ARGS, GType); \
+      i++; \
+    } \
+} while (0)
+
+DBusGProxyCall *
+manager_begin_bus_call (DBusGProxyManager    *manager,
+                       const char           *method,
+                       DBusGProxyCallNotify  notify,
+                       gpointer              user_data,
+                       GDestroyNotify        destroy,
+                       GType                 first_arg_type,
+                       ...)
+{
+  DBusGProxyCall *call;
+  va_list args;
+  GValueArray *arg_values;
+  
+  va_start (args, first_arg_type);
+
+  if (!manager->bus_proxy)
+    {
+      manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
+                                        "name", DBUS_SERVICE_DBUS,
+                                        "path", DBUS_PATH_DBUS,
+                                        "interface", DBUS_INTERFACE_DBUS,
+                                        NULL);
+      manager->bus_proxy->manager = manager;
+    }
+
+  DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
+  
+  call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values));
+
+  g_value_array_free (arg_values);
+
+  va_end (args);
+
+  return call;
+}
+
 /** @} End of DBusGLibInternals */
 
 /** @addtogroup DBusGLib
@@ -1563,21 +1761,13 @@ dbus_g_proxy_new (DBusGConnection *connection,
 
   g_assert (connection != NULL);
   
-  proxy = g_object_new (DBUS_TYPE_G_PROXY, NULL);
+  proxy = g_object_new (DBUS_TYPE_G_PROXY, "name", name, "path", path_name, "interface", interface_name, NULL);
 
   /* These should all be construct-only mandatory properties,
    * for now we just don't let people use g_object_new().
    */
   
   proxy->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
-  
-  proxy->name = g_strdup (name);
-  proxy->path = g_strdup (path_name);
-  proxy->interface = g_strdup (interface_name);
-
-  proxy->for_owner = (proxy->name[0] == ':');
-  proxy->name_call = NULL;
-  proxy->associated = FALSE;
 
   dbus_g_proxy_manager_register (proxy->manager, proxy);
   
@@ -1830,33 +2020,18 @@ dbus_g_proxy_marshal_args_to_message (DBusGProxy  *proxy,
   return NULL;
 }
 
-#define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
-do { \
-  GType valtype; \
-  int i = 0; \
-  VALARRAY = g_value_array_new (6); \
-  valtype = FIRST_ARG_TYPE; \
-  while (valtype != G_TYPE_INVALID) \
-    { \
-      const char *collect_err; \
-      GValue *val; \
-      g_value_array_append (VALARRAY, NULL); \
-      val = g_value_array_get_nth (VALARRAY, i); \
-      g_value_init (val, valtype); \
-      collect_err = NULL; \
-      G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
-      valtype = va_arg (ARGS, GType); \
-      i++; \
-    } \
-} while (0)
-
-static DBusGPendingCall *
-dbus_g_proxy_begin_call_internal (DBusGProxy    *proxy,
-                                 const char    *method,
-                                 GValueArray   *args)
+static guint
+dbus_g_proxy_begin_call_internal (DBusGProxy          *proxy,
+                                 const char          *method,
+                                 DBusGProxyCallNotify notify,
+                                 gpointer             user_data,
+                                 GDestroyNotify       destroy,
+                                 GValueArray         *args)
 {
   DBusMessage *message;
   DBusPendingCall *pending;
+  GPendingNotifyClosure *closure;
+  guint call_id;
 
   g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
   g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
@@ -1874,16 +2049,32 @@ dbus_g_proxy_begin_call_internal (DBusGProxy    *proxy,
     goto oom;
   g_assert (pending != NULL);
 
-  return DBUS_G_PENDING_CALL_FROM_PENDING_CALL (pending);
+  call_id = ++proxy->call_id_counter;
+
+  if (notify != NULL)
+    {
+      closure = g_new (GPendingNotifyClosure, 1);
+      closure->proxy = proxy; /* No need to ref as the lifecycle is tied to proxy */
+      closure->call_id = call_id;
+      closure->func = notify;
+      closure->data = user_data;
+      closure->free_data_func = destroy;
+      dbus_pending_call_set_notify (pending, d_pending_call_notify,
+                                   closure,
+                                   d_pending_call_free);
+    }
+
+  g_hash_table_insert (proxy->pending_calls, GUINT_TO_POINTER (call_id), pending);
+  
+  return call_id;
  oom:
   g_error ("Out of memory");
-  return NULL;
+  return 0;
 }
 
 static gboolean
-dbus_g_pending_call_end_valist (DBusGConnection   *connection,
-                               DBusGProxy        *proxycon,
-                               DBusGPendingCall  *pending,
+dbus_g_proxy_end_call_internal (DBusGProxy        *proxy,
+                               guint              call_id,
                                GError           **error,
                                GType              first_arg_type,
                                va_list            args)
@@ -1896,13 +2087,17 @@ dbus_g_pending_call_end_valist (DBusGConnection   *connection,
   int n_retvals_processed;
   gboolean ret;
   GType valtype;
+  DBusPendingCall *pending;
 
   reply = NULL;
   ret = FALSE;
   n_retvals_processed = 0;
   over = 0;
-  dbus_pending_call_block (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (pending));
-  reply = dbus_pending_call_steal_reply (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (pending));
+
+  pending = g_hash_table_lookup (proxy->pending_calls, GUINT_TO_POINTER (call_id));
+  
+  dbus_pending_call_block (pending);
+  reply = dbus_pending_call_steal_reply (pending);
 
   g_assert (reply != NULL);
 
@@ -1921,9 +2116,8 @@ dbus_g_pending_call_end_valist (DBusGConnection   *connection,
          GValue gvalue = { 0, };
          DBusGValueMarshalCtx context;
 
-         context.gconnection = connection;
-         context.proxy = proxycon;
-
+         context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (proxy->manager->connection);
+         context.proxy = proxy;
 
          arg_type = dbus_message_iter_get_arg_type (&msgiter);
          if (arg_type == DBUS_TYPE_INVALID)
@@ -2039,76 +2233,44 @@ dbus_g_pending_call_end_valist (DBusGConnection   *connection,
     }
   va_end (args_unwind);
 
-  if (pending)
-    dbus_g_pending_call_unref (pending);
+  g_hash_table_remove (proxy->pending_calls, GUINT_TO_POINTER (call_id));
+
   if (reply)
     dbus_message_unref (reply);
   return ret;
 }
 
-static gboolean
-dbus_g_pending_call_end (DBusGConnection   *connection,
-                        DBusGProxy        *proxycon,
-                        DBusGPendingCall  *pending,
-                        GError           **error,
-                        GType              first_arg_type,
-                        ...)
-{
-  va_list args;
-  gboolean ret;
-
-  va_start (args, first_arg_type);
-
-  ret = dbus_g_pending_call_end_valist (connection, proxycon, pending,
-                                       error, first_arg_type, args);
-
-  va_end (args);
-
-  return ret;
-}
-
-static gboolean
-dbus_g_proxy_end_call_internal (DBusGProxy       *proxy,
-                               DBusGPendingCall *pending,
-                               GError          **error,
-                               GType             first_arg_type,
-                               va_list           args)
-{
-  return dbus_g_pending_call_end_valist (DBUS_G_CONNECTION_FROM_CONNECTION (proxy->manager->connection),
-                                        proxy,
-                                        pending,
-                                        error,
-                                        first_arg_type,
-                                        args);
-}
-
-
 /**
- * Invokes a method on a remote interface. This function does not
- * block; instead it returns an opaque #DBusPendingCall object that
- * tracks the pending call.  The method call will not be sent over the
- * wire until the application returns to the main loop, or blocks in
- * dbus_connection_flush() to write out pending data.  The call will
- * be completed after a timeout, or when a reply is received.
- * To collect the results of the call (which may be an error,
- * or a reply), use dbus_g_proxy_end_call().
+ * Asynchronously invokes a method on a remote interface. The method
+ * call will not be sent over the wire until the application returns
+ * to the main loop, or blocks in dbus_connection_flush() to write out
+ * pending data.  The call will be completed after a timeout, or when
+ * a reply is received.  When the call returns, the callback specified
+ * will be invoked; you can then collect the results of the call
+ * (which may be an error, or a reply), use dbus_g_proxy_end_call().
  *
  * @todo this particular function shouldn't die on out of memory,
  * since you should be able to do a call with large arguments.
  * 
  * @param proxy a proxy for a remote interface
  * @param method the name of the method to invoke
+ * @param notify callback to be invoked when method returns
+ * @param user_data user data passed to callback
+ * @param destroy function called to destroy user_data
  * @param first_arg_type type of the first argument
  *
- * @returns opaque pending call object
+ * @returns call identifier
  *  */
-DBusGPendingCall*
-dbus_g_proxy_begin_call (DBusGProxy *proxy,
-                        const char  *method,
-                        GType       first_arg_type,
-                        ...)
+DBusGProxyCall *
+dbus_g_proxy_begin_call (DBusGProxy          *proxy,
+                        const char          *method,
+                        DBusGProxyCallNotify notify,
+                        gpointer             user_data,
+                        GDestroyNotify       destroy,
+                        GType                first_arg_type,
+                        ...)
 {
-  DBusGPendingCall *pending;
+  guint call_id;
   va_list args;
   GValueArray *arg_values;
   
@@ -2116,21 +2278,21 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy,
 
   DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
   
-  pending = dbus_g_proxy_begin_call_internal (proxy, method, arg_values);
+  call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values);
 
   g_value_array_free (arg_values);
 
   va_end (args);
 
-  return pending;
+  return DBUS_G_PROXY_ID_TO_CALL (call_id);
 }
 
 /**
  * Collects the results of a method call. The method call was normally
- * initiated with dbus_g_proxy_end_call(). This function will block if
- * the results haven't yet been received; use
- * dbus_g_pending_call_set_notify() to be notified asynchronously that a
- * pending call has been completed. If it's completed, it will not block.
+ * initiated with dbus_g_proxy_end_call(). You may use this function
+ * outside of the callback given to dbus_g_proxy_begin_call; in that
+ * case this function will block if the results haven't yet been
+ * received.
  *
  * If the call results in an error, the error is set as normal for
  * GError and the function returns #FALSE.
@@ -2139,17 +2301,15 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy,
  * method are stored in the provided varargs list.
  * The list should be terminated with G_TYPE_INVALID.
  *
- * This function unrefs the pending call.
- *
  * @param proxy a proxy for a remote interface
- * @param pending the pending call from dbus_g_proxy_begin_call()
+ * @param call_id the pending call ID from dbus_g_proxy_begin_call()
  * @param error return location for an error
  * @param first_arg_type type of first "out" argument
  * @returns #FALSE if an error is set
  */
 gboolean
 dbus_g_proxy_end_call (DBusGProxy          *proxy,
-                       DBusGPendingCall    *pending,
+                       DBusGProxyCall      *call,
                        GError             **error,
                        GType                first_arg_type,
                        ...)
@@ -2159,7 +2319,7 @@ dbus_g_proxy_end_call (DBusGProxy          *proxy,
 
   va_start (args, first_arg_type);
 
-  ret = dbus_g_proxy_end_call_internal (proxy, pending, error, first_arg_type, args);
+  ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
 
   va_end (args);
   
@@ -2187,7 +2347,7 @@ dbus_g_proxy_call (DBusGProxy        *proxy,
                   ...)
 {
   gboolean ret;
-  DBusGPendingCall *pending;
+  guint call_id;
   va_list args;
   GValueArray *in_args;
 
@@ -2195,12 +2355,12 @@ dbus_g_proxy_call (DBusGProxy        *proxy,
 
   DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
 
-  pending = dbus_g_proxy_begin_call_internal (proxy, method, in_args);
+  call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args);
 
   g_value_array_free (in_args);
 
   first_arg_type = va_arg (args, GType);
-  ret = dbus_g_proxy_end_call_internal (proxy, pending, error, first_arg_type, args);
+  ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
 
   va_end (args);
 
@@ -2256,6 +2416,35 @@ dbus_g_proxy_call_no_reply (DBusGProxy               *proxy,
 }
 
 /**
+ * Cancels a pending method call. The method call was normally
+ * initiated with dbus_g_proxy_begin_call().  This function
+ * may not be used on pending calls that have already been
+ * ended with dbus_g_proxy_end_call.
+ *
+ * @param proxy a proxy for a remote interface
+ * @param call_id the pending call ID from dbus_g_proxy_begin_call()
+ */
+void
+dbus_g_proxy_cancel_call (DBusGProxy        *proxy,
+                         DBusGProxyCall    *call)
+{
+  guint call_id;
+  DBusPendingCall *pending;
+  
+  g_return_if_fail (DBUS_IS_G_PROXY (proxy));
+  g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
+
+  call_id = DBUS_G_PROXY_CALL_TO_ID (call);
+
+  pending = g_hash_table_lookup (proxy->pending_calls, GUINT_TO_POINTER (call_id));
+  g_return_if_fail (pending != NULL);
+
+  dbus_pending_call_cancel (pending);
+
+  g_hash_table_remove (proxy->pending_calls, GUINT_TO_POINTER (call_id));
+}
+
+/**
  * Sends a message to the interface we're proxying for.  Does not
  * block or wait for a reply. The message is only actually written out
  * when you return to the main loop or block in
index fd71d74..cac774c 100644 (file)
@@ -23,6 +23,9 @@ static gboolean proxy_destroyed = FALSE;
 static gboolean proxy_destroy_and_nameowner = FALSE;
 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 gboolean
 timed_exit (gpointer loop)
 {
@@ -168,8 +171,59 @@ sig2_signal_handler (DBusGProxy  *proxy,
   g_source_remove (exit_timeout);
 }
 
-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 DBusGProxyCall *echo_call;
+static guint n_times_echo_cb_entered;
+static void
+echo_received_cb (DBusGProxy *proxy,
+                 DBusGProxyCall *call,
+                 gpointer data)
+{
+  GError *error;
+  char *echo_data;
+
+  g_assert (call == echo_call);
+  g_assert (data == NULL);
+
+  error = NULL;
+  echo_data = NULL;
+  n_times_echo_cb_entered++;
+
+  if (!dbus_g_proxy_end_call (proxy, call, &error,
+                             G_TYPE_STRING,
+                             &echo_data,
+                             G_TYPE_INVALID))
+    lose_gerror ("Failed to complete async Echo", error);
+  g_assert (echo_data != NULL);
+  g_print ("Async echo gave \"%s\"", echo_data); 
+  g_main_loop_quit (loop);
+  g_source_remove (exit_timeout);
+}
+
+static void
+increment_received_cb (DBusGProxy *proxy,
+                      DBusGProxyCall *call,
+                      gpointer data)
+{
+  GError *error;
+  char *echo_data;
+  guint val;
+
+  g_assert (!strcmp (data, "moo"));
+
+  error = NULL;
+  echo_data = NULL;
+  if (!dbus_g_proxy_end_call (proxy, call, &error,
+                             G_TYPE_UINT, &val,
+                             G_TYPE_INVALID))
+    lose_gerror ("Failed to complete (async) Increment call", error);
+
+  if (val != 43)
+    lose ("Increment call returned %d, should be 43", val);
+  
+  g_print ("Async increment gave \"%d\"", val); 
+  g_main_loop_quit (loop);
+  g_source_remove (exit_timeout);
+}
 
 static void
 lose (const char *str, ...)
@@ -215,10 +269,10 @@ main (int argc, char **argv)
   DBusGProxy *driver;
   DBusGProxy *proxy;
   DBusGProxy *proxy2;
-  DBusGPendingCall *call;
   char **name_list;
   guint name_list_len;
   guint i;
+  DBusGProxyCall *call;
   guint32 result;
   char *v_STRING_2;
   guint32 v_UINT32_2;
@@ -262,12 +316,11 @@ main (int argc, char **argv)
                               NULL);
   /* Call ListNames method */
   
-  call = dbus_g_proxy_begin_call (driver, "ListNames", G_TYPE_INVALID);
-
   error = NULL;
-  if (!dbus_g_proxy_end_call (driver, call, &error,
-                              G_TYPE_STRV, &name_list,
-                              G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (driver, "ListNames", &error,
+                         G_TYPE_INVALID,
+                         G_TYPE_STRV, &name_list,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete ListNames call", error);
 
   g_print ("Names on the message bus:\n");
@@ -285,53 +338,42 @@ main (int argc, char **argv)
 
   g_print ("calling ThisMethodDoesNotExist\n");
   /* Test handling of unknown method */
-  call = dbus_g_proxy_begin_call (driver, "ThisMethodDoesNotExist",
-                                  G_TYPE_STRING,
-                                  "blah blah blah blah blah",
-                                  G_TYPE_INT,
-                                  10,
-                                  G_TYPE_INVALID);
-
-  error = NULL;
-  if (dbus_g_proxy_end_call (driver, call, &error,
-                            G_TYPE_INVALID))
+  if (dbus_g_proxy_call (driver, "ThisMethodDoesNotExist", &error,
+                        G_TYPE_STRING,
+                        "blah blah blah blah blah",
+                        G_TYPE_INT,
+                        10,
+                        G_TYPE_INVALID, G_TYPE_INVALID) != FALSE)
     lose ("Calling nonexistent method succeeded!");
 
   g_print ("Got EXPECTED error from calling unknown method: %s\n", error->message);
-  g_error_free (error);
+  g_clear_error (&error);
 
   run_mainloop ();
   
   /* Activate a service */
   g_print ("Activating echo service\n");
-  call = dbus_g_proxy_begin_call (driver, "StartServiceByName",
-                                  G_TYPE_STRING,
-                                  "org.freedesktop.DBus.TestSuiteEchoService",
-                                  G_TYPE_UINT,
-                                  0,
-                                  G_TYPE_INVALID);
-
-  error = NULL;
-  if (!dbus_g_proxy_end_call (driver, call, &error,
-                              G_TYPE_UINT, &result,
-                              G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (driver, "StartServiceByName", &error,
+                         G_TYPE_STRING,
+                         "org.freedesktop.DBus.TestSuiteEchoService",
+                         G_TYPE_UINT, 0,
+                         G_TYPE_INVALID,
+                         G_TYPE_UINT, &result,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete Activate call", error);
 
   g_print ("Starting echo service result = 0x%x\n", result);
 
   /* Activate a service again */
   g_print ("Activating echo service again\n");
-  call = dbus_g_proxy_begin_call (driver, "StartServiceByName",
-                                  G_TYPE_STRING,
-                                  "org.freedesktop.DBus.TestSuiteEchoService",
-                                  G_TYPE_UINT,
-                                  0,
-                                  DBUS_TYPE_INVALID);
-
-  error = NULL;
-  if (!dbus_g_proxy_end_call (driver, call, &error,
-                             G_TYPE_UINT, &result,
-                             G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (driver, "StartServiceByName", &error,
+                         G_TYPE_STRING,
+                         "org.freedesktop.DBus.TestSuiteEchoService",
+                         G_TYPE_UINT,
+                         0,
+                         G_TYPE_INVALID,
+                         G_TYPE_UINT, &result,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete Activate call", error);
 
   g_print ("Duplicate start of echo service = 0x%x\n", result);
@@ -351,20 +393,25 @@ main (int argc, char **argv)
   run_mainloop ();
 
   g_print ("Calling Echo\n");
-  call = dbus_g_proxy_begin_call (proxy, "Echo",
-                                  G_TYPE_STRING,
-                                  "my string hello",
-                                  G_TYPE_INVALID);
-
-  error = NULL;
-  if (!dbus_g_proxy_end_call (proxy, call, &error,
-                              G_TYPE_STRING, &v_STRING_2,
-                              G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (proxy, "Echo", &error,
+                         G_TYPE_STRING, "my string hello",
+                         G_TYPE_INVALID,
+                         G_TYPE_STRING, &v_STRING_2,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete Echo call", error);
 
   g_print ("String echoed = \"%s\"\n", v_STRING_2);
   g_free (v_STRING_2);
 
+  g_print ("Calling Echo (async)\n");
+  echo_call = dbus_g_proxy_begin_call (proxy, "Echo",
+                                      echo_received_cb, NULL, NULL,
+                                      G_TYPE_STRING, "my string hello",
+                                      G_TYPE_INVALID);
+  dbus_g_connection_flush (connection);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+
   /* Test oneway call and signal handling */
 
   g_print ("Testing Foo emission\n");
@@ -417,10 +464,8 @@ main (int argc, char **argv)
     lose_gerror ("Failed to create proxy for name owner", error);
 
   g_print ("Calling DoNothing\n");
-  call = dbus_g_proxy_begin_call (proxy, "DoNothing",
-                                  G_TYPE_INVALID);
-  error = NULL;
-  if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (proxy, "DoNothing", &error,
+                         G_TYPE_INVALID, G_TYPE_INVALID))
     lose_gerror ("Failed to complete DoNothing call", error);
 
   g_print ("Calling Increment\n");
@@ -431,15 +476,24 @@ main (int argc, char **argv)
                          G_TYPE_UINT, &v_UINT32_2,
                          G_TYPE_INVALID))
     lose_gerror ("Failed to complete Increment call", error);
+  g_assert (n_times_echo_cb_entered == 1);
 
   if (v_UINT32_2 != 43)
     lose ("Increment call returned %d, should be 43", v_UINT32_2);
 
+  call = dbus_g_proxy_begin_call (proxy, "Increment",
+                                 increment_received_cb, g_strdup ("moo"), g_free,
+                                 G_TYPE_UINT, 42,
+                                 G_TYPE_INVALID);
+  dbus_g_connection_flush (connection);
+  exit_timeout = g_timeout_add (5000, timed_exit, loop);
+  g_main_loop_run (loop);
+
   g_print ("Calling ThrowError\n");
-  call = dbus_g_proxy_begin_call (proxy, "ThrowError", G_TYPE_INVALID);
-  error = NULL;
-  if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID) != FALSE)
+  if (dbus_g_proxy_call (proxy, "ThrowError", &error,
+                        G_TYPE_INVALID, G_TYPE_INVALID) != FALSE)
     lose ("ThrowError call unexpectedly succeeded!");
+
   if (!dbus_g_error_has_name (error, "org.freedesktop.DBus.Tests.MyObject.Foo"))
     lose ("ThrowError call returned unexpected error \"%s\": %s", dbus_g_error_get_name (error),
          error->message);
@@ -447,14 +501,13 @@ main (int argc, char **argv)
   g_print ("ThrowError failed (as expected) returned error: %s\n", error->message);
   g_clear_error (&error);
 
-  g_print ("Calling Uppercase\n");
-  call = dbus_g_proxy_begin_call (proxy, "Uppercase",
-                                 G_TYPE_STRING, "foobar",
-                                 G_TYPE_INVALID);
   error = NULL;
-  if (!dbus_g_proxy_end_call (proxy, call, &error,
-                             G_TYPE_STRING, &v_STRING_2,
-                             G_TYPE_INVALID))
+  g_print ("Calling Uppercase\n");
+  if (!dbus_g_proxy_call (proxy, "Uppercase", &error,
+                         G_TYPE_STRING, "foobar",
+                         G_TYPE_INVALID,
+                         G_TYPE_STRING, &v_STRING_2,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete Uppercase call", error);
   if (strcmp ("FOOBAR", v_STRING_2) != 0)
     lose ("Uppercase call returned unexpected string %s", v_STRING_2);
@@ -463,16 +516,14 @@ main (int argc, char **argv)
   run_mainloop ();
 
   g_print ("Calling ManyArgs\n");
-  call = dbus_g_proxy_begin_call (proxy, "ManyArgs",
-                                 G_TYPE_UINT, 26,
-                                 G_TYPE_STRING, "bazwhee",
-                                 G_TYPE_DOUBLE, G_PI,
-                                 G_TYPE_INVALID);
-  error = NULL;
-  if (!dbus_g_proxy_end_call (proxy, call, &error,
-                             G_TYPE_DOUBLE, &v_DOUBLE_2,
-                             G_TYPE_STRING, &v_STRING_2,
-                             G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (proxy, "ManyArgs", &error,
+                         G_TYPE_UINT, 26,
+                         G_TYPE_STRING, "bazwhee",
+                         G_TYPE_DOUBLE, G_PI,
+                         G_TYPE_INVALID,
+                         G_TYPE_DOUBLE, &v_DOUBLE_2,
+                         G_TYPE_STRING, &v_STRING_2,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete ManyArgs call", error);
   if (v_DOUBLE_2 < 55 || v_DOUBLE_2 > 56)
     lose ("ManyArgs call returned unexpected double value %f", v_DOUBLE_2);
@@ -827,9 +878,9 @@ main (int argc, char **argv)
                            DBUS_TYPE_G_OBJECT_PATH,
                            &ret_path,
                            G_TYPE_INVALID))
-      lose_gerror ("Failed to complete (wrapped) Objpath call 2", error);
+      lose_gerror ("Failed to complete Objpath call 2", error);
     if (strcmp ("/org/freedesktop/DBus/Tests/MyTestObject2", ret_path) != 0)
-      lose ("(wrapped) objpath call 2 returned unexpected path %s",
+      lose ("Objpath call 2 returned unexpected path %s",
            ret_path);
 
     ret_proxy = dbus_g_proxy_new_for_name_owner (connection,
@@ -837,6 +888,7 @@ main (int argc, char **argv)
                                                 ret_path,
                                                 "org.freedesktop.DBus.Tests.FooObject",
                                                 &error);
+    g_free (ret_path);
     
     val = 0;
     if (!org_freedesktop_DBus_Tests_FooObject_get_value (ret_proxy, &val, &error))
@@ -982,7 +1034,7 @@ main (int argc, char **argv)
     lose ("Didn't get proxy_destroyed");
   g_print ("Proxy destroyed successfully\n");
 
-  g_object_unref (G_OBJECT (proxy));
+  /* Don't need to unref, proxy was destroyed */
 
   run_mainloop ();
 
@@ -1122,12 +1174,10 @@ main (int argc, char **argv)
     lose_gerror ("Failed to create proxy for name owner", error);
 
   g_print ("Testing introspect\n");
-  call = dbus_g_proxy_begin_call (proxy, "Introspect",
-                                 G_TYPE_INVALID);
-  error = NULL;
-  if (!dbus_g_proxy_end_call (proxy, call, &error,
-                             G_TYPE_STRING, &v_STRING_2,
-                             G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (proxy, "Introspect", &error,
+                         G_TYPE_INVALID,
+                         G_TYPE_STRING, &v_STRING_2,
+                         G_TYPE_INVALID))
     lose_gerror ("Failed to complete Introspect call", error);
 
   /* Could just do strcmp(), but that seems more fragile */
index fa9a9da..9bd95ea 100644 (file)
@@ -32,7 +32,7 @@ filter_func (DBusConnection     *connection,
              DBusMessage        *message,
              void               *user_data)
 {
-  print_message (message);
+  print_message (message, FALSE);
   
   if (dbus_message_is_signal (message,
                               DBUS_INTERFACE_LOCAL,
index b1ea24e..65faa1b 100644 (file)
@@ -43,7 +43,7 @@ struct NamesModel
   GtkListStore parent;
   DBusGConnection *connection;
   DBusGProxy *driver_proxy;
-  DBusGPendingCall *pending_list_names;
+  DBusGProxyCall *pending_list_names;
 };
 
 struct NamesModelClass
@@ -59,7 +59,8 @@ struct NamesModelClass
 #define NAMES_MODEL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NAMES_MODEL, NamesModelClass))
 
 static void
-have_names_notify (DBusGPendingCall *call,
+have_names_notify (DBusGProxy       *proxy,
+                  DBusGProxyCall   *call,
                    void             *data)
 {
   NamesModel *names_model;
@@ -69,7 +70,7 @@ have_names_notify (DBusGPendingCall *call,
 
   names_model = NAMES_MODEL (data);
 
-  g_assert (names_model->pending_list_names);
+  g_assert (names_model->pending_list_names == call);
   g_assert (names_model->driver_proxy);
 
   names = NULL;
@@ -195,8 +196,8 @@ names_model_reload (NamesModel *names_model)
 
   if (names_model->pending_list_names)
     {
-      dbus_g_pending_call_cancel (names_model->pending_list_names);
-      dbus_g_pending_call_unref (names_model->pending_list_names);
+      dbus_g_proxy_cancel_call (names_model->driver_proxy,
+                               names_model->pending_list_names);
       names_model->pending_list_names = NULL;
     }
   
@@ -208,10 +209,8 @@ names_model_reload (NamesModel *names_model)
   names_model->pending_list_names =
     dbus_g_proxy_begin_call (names_model->driver_proxy,
                              "ListNames",
+                            have_names_notify, names_model, NULL,
                              G_TYPE_INVALID);
-
-  dbus_g_pending_call_set_notify (names_model->pending_list_names,
-                                  have_names_notify, names_model, NULL);
 }
 
 static void
index bd47666..e201fda 100644 (file)
@@ -40,7 +40,7 @@ type_to_name (int message_type)
 }
 
 static void
-print_iter (DBusMessageIter *iter, int depth)
+print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
 {
   do
     {
@@ -62,7 +62,11 @@ print_iter (DBusMessageIter *iter, int depth)
        {
        case DBUS_TYPE_STRING:
           dbus_message_iter_get_basic (iter, &str);
-         printf ("string \"%s\"\n", str);
+         if (!literal)
+           printf ("string \"");
+         printf ("%s", str);
+         if (!literal)
+           printf ("\"\n");
          break;
 
        case DBUS_TYPE_INT32:
@@ -97,7 +101,7 @@ print_iter (DBusMessageIter *iter, int depth)
            dbus_message_iter_recurse (iter, &subiter);
 
            printf ("variant:");
-           print_iter (&subiter, depth);
+           print_iter (&subiter, literal, depth);
            break;
          }
        case DBUS_TYPE_ARRAY:
@@ -110,7 +114,7 @@ print_iter (DBusMessageIter *iter, int depth)
            printf("[");
            while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
              {
-               print_iter (&subiter, depth);
+               print_iter (&subiter, literal, depth);
                dbus_message_iter_next (&subiter);
                if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_INVALID)
                  printf (",");
@@ -125,9 +129,9 @@ print_iter (DBusMessageIter *iter, int depth)
            dbus_message_iter_recurse (iter, &subiter);
 
            printf("{");
-           print_iter (&subiter, depth);
+           print_iter (&subiter, literal, depth);
            dbus_message_iter_next (&subiter);
-           print_iter (&subiter, depth);
+           print_iter (&subiter, literal, depth);
            printf("}");
            break;
          }
@@ -141,7 +145,7 @@ print_iter (DBusMessageIter *iter, int depth)
 }
 
 void
-print_message (DBusMessage *message)
+print_message (DBusMessage *message, dbus_bool_t literal)
 {
   DBusMessageIter iter;
   const char *sender;
@@ -151,37 +155,40 @@ print_message (DBusMessage *message)
   message_type = dbus_message_get_type (message);
   sender = dbus_message_get_sender (message);
   destination = dbus_message_get_destination (message);
-
-  printf ("%s sender=%s -> dest=%s",
-          type_to_name (message_type),
-          sender ? sender : "(null sender)",
-          destination ? destination : "(null destination)");
-         
-  switch (message_type)
+  
+  if (!literal)
     {
-    case DBUS_MESSAGE_TYPE_METHOD_CALL:
-    case DBUS_MESSAGE_TYPE_SIGNAL:
-      printf (" interface=%s; member=%s\n",
-              dbus_message_get_interface (message),
-              dbus_message_get_member (message));
-      break;
+      printf ("%s sender=%s -> dest=%s",
+             type_to_name (message_type),
+             sender ? sender : "(null sender)",
+             destination ? destination : "(null destination)");
+  
+      switch (message_type)
+       {
+       case DBUS_MESSAGE_TYPE_METHOD_CALL:
+       case DBUS_MESSAGE_TYPE_SIGNAL:
+         printf (" interface=%s; member=%s\n",
+                 dbus_message_get_interface (message),
+                 dbus_message_get_member (message));
+         break;
       
-    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
-      printf ("\n");
-      break;
+       case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+         printf ("\n");
+         break;
 
-    case DBUS_MESSAGE_TYPE_ERROR:
-      printf (" error_name=%s\n",
-              dbus_message_get_error_name (message));
-      break;
+       case DBUS_MESSAGE_TYPE_ERROR:
+         printf (" error_name=%s\n",
+                 dbus_message_get_error_name (message));
+         break;
 
-    default:
-      printf ("\n");
-      break;
+       default:
+         printf ("\n");
+         break;
+       }
     }
 
   dbus_message_iter_init (message, &iter);
-  print_iter (&iter, 1);
+  print_iter (&iter, literal, 1);
   
 }
 
index c40e766..a999450 100644 (file)
@@ -26,6 +26,6 @@
 #include <string.h>
 #include <dbus/dbus.h>
 
-void print_message (DBusMessage *message);
+void print_message (DBusMessage *message, dbus_bool_t literal);
 
 #endif /* DBUS_PRINT_MESSAGE_H */
index 37b7206..477a8ab 100644 (file)
@@ -32,7 +32,7 @@ static const char *appname;
 static void
 usage (int ecode)
 {
-  fprintf (stderr, "Usage: %s [--help] [--system | --session] [--dest=NAME] [--type=TYPE] [--print-reply] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname);
+  fprintf (stderr, "Usage: %s [--help] [--system | --session] [--dest=NAME] [--type=TYPE] [--print-reply=(literal)] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname);
   exit (ecode);
 }
 
@@ -183,6 +183,7 @@ main (int argc, char *argv[])
   DBusError error;
   DBusMessage *message;
   int print_reply;
+  int print_reply_literal;
   int reply_timeout;
   DBusMessageIter iter;
   int i;
@@ -199,6 +200,7 @@ main (int argc, char *argv[])
     usage (1);
 
   print_reply = FALSE;
+  print_reply_literal = FALSE;
   reply_timeout = -1;
   
   for (i = 1; i < argc && name == NULL; i++)
@@ -209,10 +211,12 @@ main (int argc, char *argv[])
        type = DBUS_BUS_SYSTEM;
       else if (strcmp (arg, "--session") == 0)
        type = DBUS_BUS_SESSION;
-      else if (strcmp (arg, "--print-reply") == 0)
+      else if (strncmp (arg, "--print-reply", 13) == 0)
        {
          print_reply = TRUE;
          message_type = DBUS_MESSAGE_TYPE_METHOD_CALL;
+         if (*(arg + 13) != '\0')
+           print_reply_literal = TRUE;
        }
       else if (strstr (arg, "--reply-timeout=") == arg)
        {
@@ -436,7 +440,7 @@ main (int argc, char *argv[])
 
       if (reply)
         {
-          print_message (reply);
+          print_message (reply, print_reply_literal);
           dbus_message_unref (reply);
         }
     }
index 95d00c1..ae44075 100644 (file)
@@ -147,14 +147,12 @@ load_child_nodes (const char *service_name,
   while (tmp != NULL)
     {
       DBusGProxy *proxy;
-      DBusGPendingCall *call;
       char *data;
       NodeInfo *child;
       NodeInfo *complete_child;
       int save_len;
 
       complete_child = NULL;
-      call = NULL;
       
       child = tmp->data;
 
@@ -183,17 +181,11 @@ load_child_nodes (const char *service_name,
             goto done;
         }
   
-      call = dbus_g_proxy_begin_call (proxy, "Introspect",
-                                      G_TYPE_INVALID);
-      
-      data = NULL;
-      if (!dbus_g_proxy_end_call (proxy, call, error, G_TYPE_STRING, &data,
-                                  G_TYPE_INVALID))
-       {
-         call = NULL;
+      if (!dbus_g_proxy_call (proxy, "Introspect", error,
+                             G_TYPE_STRING, &data,
+                             G_TYPE_INVALID,
+                             G_TYPE_INVALID))
          goto done;
-       }
-      call = NULL;
       
       complete_child = description_load_from_string (data, -1, error);
       g_free (data);
@@ -204,8 +196,6 @@ load_child_nodes (const char *service_name,
         }
       
     done:
-      if (call)
-        dbus_g_pending_call_unref (call);
       g_object_unref (proxy);
 
       if (complete_child == NULL)
@@ -271,7 +261,6 @@ static void*
 load_from_service_thread_func (void *thread_data)
 {  
   DBusGProxy *root_proxy;
-  DBusGPendingCall *call;
   const char *data;
   NodeInfo *node;
   GString *path;
@@ -280,7 +269,6 @@ load_from_service_thread_func (void *thread_data)
   lfsd = thread_data;
 
   node = NULL;
-  call = NULL;
   path = NULL;
  
 #if 1
@@ -304,19 +292,15 @@ load_from_service_thread_func (void *thread_data)
     }
 #endif
   
-  call = dbus_g_proxy_begin_call (root_proxy, "Introspect",
-                                  G_TYPE_INVALID);
-
-  data = NULL;
-  if (!dbus_g_proxy_end_call (root_proxy, call, &lfsd->error, G_TYPE_STRING, &data,
-                              G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (root_proxy, "Introspect", &lfsd->error,
+                         G_TYPE_INVALID,
+                         G_TYPE_STRING, &data,
+                         G_TYPE_INVALID))
     {
-      call = NULL;
       g_printerr ("Failed to Introspect() %s\n",
-                  dbus_g_proxy_get_bus_name (root_proxy));
+                 dbus_g_proxy_get_bus_name (root_proxy));
       goto out;
     }
-  call = NULL;
 
   node = description_load_from_string (data, -1, &lfsd->error);
 
@@ -338,9 +322,6 @@ load_from_service_thread_func (void *thread_data)
     }
   
  out:
-  if (call)
-    dbus_g_pending_call_unref (call);
-    
   g_object_unref (root_proxy);
 
   if (path)
index e9fe3ce..91052cf 100644 (file)
@@ -37,7 +37,6 @@ main (int argc, char *argv[])
 {
   DBusGConnection *connection;
   DBusGProxy *proxy;
-  DBusGPendingCall *call;
   GError *error;
   const char *service;
   const char *path;
@@ -64,9 +63,10 @@ main (int argc, char *argv[])
   proxy = dbus_g_proxy_new_for_name (connection,
                                     service, path,
                                     DBUS_INTERFACE_INTROSPECTABLE);
-  call = dbus_g_proxy_begin_call (proxy, "Introspect", G_TYPE_INVALID);
-  if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_STRING,
-                             &introspect_data, G_TYPE_INVALID))
+  if (!dbus_g_proxy_call (proxy, "Introspect",  &error,
+                         G_TYPE_INVALID,
+                         G_TYPE_STRING, &introspect_data,
+                         G_TYPE_INVALID))
     {
       fprintf (stderr, "Failed to get introspection data: %s\n",
                error->message);