diff options
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | bus/signals.c | 6 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 2 | ||||
| -rw-r--r-- | glib/dbus-glib.h | 81 | ||||
| -rw-r--r-- | glib/dbus-gmain.c | 37 | ||||
| -rw-r--r-- | glib/dbus-gproxy.c | 629 | 
6 files changed, 676 insertions, 87 deletions
@@ -1,3 +1,11 @@ +2003-09-23  Havoc Pennington  <hp@redhat.com> + +	* glib/dbus-gproxy.c (dbus_gproxy_connect_signal): implement +	(dbus_gproxy_disconnect_signal): implement +	(dbus_gproxy_manager_remove_signal_match): implement +	(dbus_gproxy_manager_add_signal_match): implement +	(dbus_gproxy_oneway_call): implement +  2003-09-23  Havoc Pennington  <hp@pobox.com>  	* glib/dbus-gproxy.c (struct DBusGProxy): convert to a GObject diff --git a/bus/signals.c b/bus/signals.c index db7b0665..30d977c3 100644 --- a/bus/signals.c +++ b/bus/signals.c @@ -690,7 +690,11 @@ bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,                                 DBusList       **recipients_p)  {    /* FIXME for now this is a wholly unoptimized linear search */ - +  /* Guessing the important optimization is to skip the signal-related +   * match lists when processing method call and exception messages. +   * So separate match rule lists for signals? +   */ +      DBusList *link;    _dbus_assert (*recipients_p == NULL); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 2ed421d7..824d85bf 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -4818,7 +4818,7 @@ decode_header_data (const DBusString   *data,            _dbus_verbose ("No path field provided\n");            return FALSE;          } -      /* FIXME make this optional, at least for method calls */ +      /* FIXME make this optional, only for method calls */        if (fields[DBUS_HEADER_FIELD_INTERFACE].offset < 0)          {            _dbus_verbose ("No interface field provided\n"); diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h index a391c4a1..79c1e116 100644 --- a/glib/dbus-glib.h +++ b/glib/dbus-glib.h @@ -34,6 +34,11 @@ G_BEGIN_DECLS  GQuark dbus_g_error_quark (void);  #define DBUS_GERROR dbus_g_error_quark () +#define DBUS_TYPE_CONNECTION (dbus_connection_get_g_type ()) +#define DBUS_TYPE_MESSAGE    (dbus_message_get_g_type ()) +GType dbus_connection_get_g_type (void) G_GNUC_CONST; +GType dbus_message_get_g_type    (void) G_GNUC_CONST; +  typedef enum  {    /* FIXME map all the DBUS_ERROR to DBUS_GERROR, should @@ -89,6 +94,9 @@ void dbus_connection_register_g_object (DBusConnection        *connection,  typedef struct DBusGProxy       DBusGProxy;  typedef struct DBusGProxyClass  DBusGProxyClass; +typedef void (* DBusGProxySignalHandler) (DBusGProxy  *proxy, +                                          DBusMessage *signal, +                                          void        *user_data);  #define DBUS_TYPE_GPROXY              (dbus_gproxy_get_type ())  #define DBUS_GPROXY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), DBUS_TYPE_GPROXY, DBusGProxy)) @@ -97,47 +105,46 @@ typedef struct DBusGProxyClass  DBusGProxyClass;  #define DBUS_IS_GPROXY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUS_TYPE_GPROXY))  #define DBUS_GPROXY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUS_TYPE_GPROXY, DBusGProxyClass)) -GType            dbus_gproxy_get_type              (void) G_GNUC_CONST; -DBusGProxy*      dbus_gproxy_new_for_service       (DBusConnection   *connection, -                                                    const char       *service_name, -                                                    const char       *path_name, -                                                    const char       *interface_name); -DBusGProxy*      dbus_gproxy_new_for_service_owner (DBusConnection   *connection, -                                                    const char       *service_name, -                                                    const char       *path_name, -                                                    const char       *interface_name, -                                                    GError          **error); -DBusGProxy*      dbus_gproxy_new_for_peer          (DBusConnection   *connection, -                                                    const char       *path_name, -                                                    const char       *interface_name); -void             dbus_gproxy_connect_signal        (DBusGProxy       *proxy, -                                                    const char       *interface_name, -                                                    const char       *signal_name, -                                                    GCallback         callback, -                                                    void             *data, -                                                    GFreeFunc         free_data_func); -void             dbus_gproxy_disconnect_signal     (DBusGProxy       *proxy, -                                                    const char       *interface_name, -                                                    const char       *signal_name, -                                                    GCallback         callback, -                                                    void             *data); -DBusPendingCall* dbus_gproxy_begin_call            (DBusGProxy       *proxy, -                                                    const char       *method, -                                                    int               first_arg_type, +GType            dbus_gproxy_get_type              (void) G_GNUC_CONST; +DBusGProxy*      dbus_gproxy_new_for_service       (DBusConnection           *connection, +                                                    const char               *service_name, +                                                    const char               *path_name, +                                                    const char               *interface_name); +DBusGProxy*      dbus_gproxy_new_for_service_owner (DBusConnection           *connection, +                                                    const char               *service_name, +                                                    const char               *path_name, +                                                    const char               *interface_name, +                                                    GError                  **error); +DBusGProxy*      dbus_gproxy_new_for_peer          (DBusConnection           *connection, +                                                    const char               *path_name, +                                                    const char               *interface_name); +void             dbus_gproxy_connect_signal        (DBusGProxy               *proxy, +                                                    const char               *signal_name, +                                                    DBusGProxySignalHandler   handler, +                                                    void                     *data, +                                                    GFreeFunc                 free_data_func); +void             dbus_gproxy_disconnect_signal     (DBusGProxy               *proxy, +                                                    const char               *signal_name, +                                                    DBusGProxySignalHandler   handler, +                                                    void                     *data); +DBusPendingCall* dbus_gproxy_begin_call            (DBusGProxy               *proxy, +                                                    const char               *method, +                                                    int                       first_arg_type,                                                      ...); -gboolean         dbus_gproxy_end_call              (DBusGProxy       *proxy, -                                                    DBusPendingCall  *pending, -                                                    GError          **error, -                                                    int               first_arg_type, +gboolean         dbus_gproxy_end_call              (DBusGProxy               *proxy, +                                                    DBusPendingCall          *pending, +                                                    GError                  **error, +                                                    int                       first_arg_type,                                                      ...); -void             dbus_gproxy_oneway_call           (DBusGProxy       *proxy, -                                                    const char       *method, -                                                    int               first_arg_type, +void             dbus_gproxy_oneway_call           (DBusGProxy               *proxy, +                                                    const char               *method, +                                                    int                       first_arg_type,                                                      ...); -void             dbus_gproxy_send                  (DBusGProxy       *proxy, -                                                    DBusMessage      *message, -                                                    dbus_uint32_t    *client_serial); +void             dbus_gproxy_send                  (DBusGProxy               *proxy, +                                                    DBusMessage              *message, +                                                    dbus_uint32_t            *client_serial); +  #undef DBUS_INSIDE_DBUS_GLIB_H diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 2e5604dc..54a2d462 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -535,6 +535,43 @@ dbus_set_g_error (GError   **gerror,                 derror->name, derror->message);    } +/** + * Get the GLib type ID for a DBusConnection boxed type. + * + * @returns GLib type + */ +GType +dbus_connection_get_g_type (void) +{ +  static GType our_type = 0; +   +  if (our_type == 0) +    our_type = g_boxed_type_register_static ("DBusConnection", +                                             (GBoxedCopyFunc) dbus_connection_ref, +                                             (GBoxedFreeFunc) dbus_connection_unref); + +  return our_type; +} + +/** + * Get the GLib type ID for a DBusMessage boxed type. + * + * @returns GLib type + */ +GType +dbus_message_get_g_type (void) +{ +  static GType our_type = 0; +   +  if (our_type == 0) +    our_type = g_boxed_type_register_static ("DBusMessage", +                                             (GBoxedCopyFunc) dbus_message_ref, +                                             (GBoxedFreeFunc) dbus_message_unref); + +  return our_type; +} + +  /** @} */ /* end of public API */  #ifdef DBUS_BUILD_TESTS diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index f27eb6d0..ebcbb5d4 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -21,6 +21,7 @@   *   */  #include "dbus-glib.h" +#include <string.h>  /**   * @addtogroup DBusGLibInternals @@ -28,19 +29,69 @@   * @{   */ +typedef struct DBusGProxyManager DBusGProxyManager; + +/** + * Internals of DBusGProxy + */ +struct DBusGProxy +{ +  GObject parent;             /**< Parent instance */ +   +  DBusGProxyManager *manager; /**< Proxy manager */ +  char *service;              /**< Service messages go to or NULL */ +  char *path;                 /**< Path messages go to or NULL */ +  char *interface;            /**< Interface messages go to or NULL */ +}; + +struct DBusGProxyClass +{ +  GObjectClass parent_class;   +}; + +static void dbus_gproxy_init          (DBusGProxy      *proxy); +static void dbus_gproxy_class_init    (DBusGProxyClass *klass); +static void dbus_gproxy_finalize      (GObject         *object); +static void dbus_gproxy_emit_received (DBusGProxy      *proxy, +                                       DBusMessage     *message); + + +/** + * A list of proxies with a given service+path+interface, used to route incoming + * signals. + */ +typedef struct +{ +  GSList *proxies; + +  char name[4]; /**< service (empty string for none), nul byte, +                 *   path, nul byte, +                 *   interface, nul byte +                 */ +   +} DBusGProxyList; +  /**   * DBusGProxyManager's primary task is to route signals to the proxies   * those signals are emitted on. In order to do this it also has to   * track the owners of the services proxies are bound to.   */ -typedef struct +struct DBusGProxyManager  {    GStaticMutex lock; /**< Thread lock */    int refcount;      /**< Reference count */    DBusConnection *connection; /**< Connection we're associated with. */ -   -} DBusGProxyManager; +  GHashTable *proxy_lists; /**< Hash used to route incoming signals +                            *   and iterate over proxies +                            */ + +}; + +static void              dbus_gproxy_manager_ref    (DBusGProxyManager *manager); +static DBusHandlerResult dbus_gproxy_manager_filter (DBusConnection    *connection, +                                                     DBusMessage       *message, +                                                     void              *user_data);  /** Lock the DBusGProxyManager */  #define LOCK_MANAGER(mgr)   (g_static_mutex_lock (&(mgr)->lock)) @@ -52,8 +103,6 @@ static int gproxy_manager_slot = -1;  /* Lock controlling get/set manager as data on each connection */  static GStaticMutex connection_gproxy_lock = G_STATIC_MUTEX_INIT; -static void dbus_gproxy_manager_ref (DBusGProxyManager *manager); -  static DBusGProxyManager*  dbus_gproxy_manager_get (DBusConnection *connection)  { @@ -90,6 +139,9 @@ dbus_gproxy_manager_get (DBusConnection *connection)    dbus_connection_set_data (connection, gproxy_manager_slot,                              manager, NULL); +  dbus_connection_add_filter (connection, dbus_gproxy_manager_filter, +                              manager, NULL); +      g_static_mutex_unlock (&connection_gproxy_lock);    return manager; @@ -119,10 +171,19 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager)    if (manager->refcount == 0)      {        UNLOCK_MANAGER (manager); + +      if (manager->proxy_lists) +        { +          g_hash_table_destroy (manager->proxy_lists); +          manager->proxy_lists = NULL; +        }        g_static_mutex_free (&manager->lock);        g_static_mutex_lock (&connection_gproxy_lock); + +      dbus_connection_remove_filter (manager->connection, dbus_gproxy_manager_filter, +                                     manager);        dbus_connection_set_data (manager->connection,                                  gproxy_manager_slot, @@ -141,29 +202,340 @@ dbus_gproxy_manager_unref (DBusGProxyManager *manager)      }  } -/** - * Internals of DBusGProxy - */ -struct DBusGProxy +static guint +tristring_hash (gconstpointer key)  { -  GObject parent; +  const char *p = key; +  guint h = *p; + +  if (h) +    { +      for (p += 1; *p != '\0'; p++) +        h = (h << 5) - h + *p; +    } + +  /* skip nul and do the next substring */ +  for (p += 1; *p != '\0'; p++) +    h = (h << 5) - h + *p; + +  /* skip nul again and another substring */ +  for (p += 1; *p != '\0'; p++) +    h = (h << 5) - h + *p; -  DBusGProxyManager *manager; /**< Proxy manager */ -  char *service;              /**< Service messages go to or NULL */ -  char *path;                 /**< Path messages go to or NULL */ -  char *interface;            /**< Interface messages go to or NULL */ -}; +  return h; +} -struct DBusGProxyClass +static gboolean +strequal_len (const char *a, +              const char *b, +              size_t     *lenp)  { -  GObjectClass parent_class;   -}; +  size_t a_len; +  size_t b_len; + +  a_len = strlen (a); +  b_len = strlen (b); + +  if (a_len != b_len) +    return FALSE; + +  if (memcmp (a, b, a_len) != 0) +    return FALSE; +   +  *lenp = a_len; + +  return TRUE; +} + +static gboolean +tristring_equal (gconstpointer  a, +                 gconstpointer  b) +{ +  const char *ap = a; +  const char *bp = b; +  size_t len; + +  if (!strequal_len (ap, bp, &len)) +    return FALSE; + +  ap += len + 1; +  bp += len + 1; + +  if (!strequal_len (ap, bp, &len)) +    return FALSE; + +  ap += len + 1; +  bp += len + 1; + +  if (strcmp (ap, bp) != 0) +    return FALSE; +   +  return TRUE; +} + +static char* +tristring_alloc_from_strings (size_t      padding_before, +                              const char *service, +                              const char *path, +                              const char *interface) +{ +  size_t service_len, iface_len, path_len, len; +  char *tri; +   +  if (service) +    service_len = strlen (service); +  else +    service_len = 0; + +  path_len = strlen (path); +   +  iface_len = strlen (interface); + +  tri = g_malloc (padding_before + service_len + path_len + iface_len + 3); + +  len = padding_before; +   +  if (service) +    memcpy (&tri[len], service, service_len); + +  len += service_len; +  tri[len] = '\0'; +  len += 1; + +  g_assert (len == (padding_before + service_len + 1)); +   +  memcpy (&tri[len], path, path_len); +  len += path_len; +  tri[len] = '\0'; +  len += 1; + +  g_assert (len == (padding_before + service_len + path_len + 2)); +   +  memcpy (&tri[len], interface, iface_len); +  len += iface_len; +  tri[len] = '\0'; +  len += 1; + +  g_assert (len == (padding_before + service_len + path_len + iface_len + 3)); + +  return tri; +} + +static char* +tristring_from_proxy (DBusGProxy *proxy) +{ +  return tristring_alloc_from_strings (0, +                                       proxy->service, +                                       proxy->path, +                                       proxy->interface); +} + +static char* +tristring_from_message (DBusMessage *message) +{ +  return tristring_alloc_from_strings (0, +                                       dbus_message_get_sender (message), +                                       dbus_message_get_path (message), +                                       dbus_message_get_interface (message)); +} + +static DBusGProxyList* +gproxy_list_new (DBusGProxy *first_proxy) +{ +  DBusGProxyList *list; +   +  list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name), +                                               first_proxy->service, +                                               first_proxy->path, +                                               first_proxy->interface); +  list->proxies = NULL; + +  return list; +} + +static void +gproxy_list_free (DBusGProxyList *list) +{ +  /* we don't hold a reference to the proxies in the list, +   * as they ref the GProxyManager +   */ +  g_slist_free (list->proxies);   + +  g_free (list); +} + +static char* +gproxy_get_match_rule (DBusGProxy *proxy) +{ +  /* FIXME Some sort of escaping is required here I think */ +   +  if (proxy->service) +    return g_strdup_printf ("type='signal',service='%s',path='%s',interface='%s'", +                            proxy->service, proxy->path, proxy->interface); +  else +    return g_strdup_printf ("type='signal',path='%s',interface='%s'", +                            proxy->path, proxy->interface); +} + +static void +dbus_gproxy_manager_register (DBusGProxyManager *manager, +                              DBusGProxy        *proxy) +{ +  DBusGProxyList *list; + +  LOCK_MANAGER (manager); + +  if (manager->proxy_lists == NULL) +    { +      list = NULL; +      manager->proxy_lists = g_hash_table_new_full (tristring_hash, +                                                    tristring_equal, +                                                    NULL, +                                                    (GFreeFunc) gproxy_list_free); +    } +  else +    { +      char *tri; + +      tri = tristring_from_proxy (proxy); +       +      list = g_hash_table_lookup (manager->proxy_lists, tri); + +      g_free (tri); +    } +       +  if (list == NULL) +    { +      list = gproxy_list_new (proxy); +       +      g_hash_table_replace (manager->proxy_lists, +                            list->name, list); +    } + +  if (list->proxies == NULL) +    { +      /* We have to add the match rule to the server, +       * but FIXME only if the server is a message bus, +       * not if it's a peer. +       */ +      char *rule; + +      rule = gproxy_get_match_rule (proxy); +       +      /* We don't check for errors; it's not like anyone would handle them, +       * and we don't want a round trip here. +       */ +      dbus_bus_add_match (manager->connection, +                          rule, NULL); + +      g_free (rule); +    } + +  g_assert (g_slist_find (list->proxies, proxy) == NULL); +   +  list->proxies = g_slist_prepend (list->proxies, proxy); +   +  UNLOCK_MANAGER (manager); +} + +static void +dbus_gproxy_manager_unregister (DBusGProxyManager *manager, +                                DBusGProxy        *proxy) +{ +  DBusGProxyList *list; +  char *tri; +   +  LOCK_MANAGER (manager); + +  if (manager->proxy_lists == NULL) +    { +      g_warning ("Trying to disconnect a signal on a proxy but none are connected\n"); +      return; +    } + +  tri = tristring_from_proxy (proxy); +   +  list = g_hash_table_lookup (manager->proxy_lists, tri); +   +  g_free (tri); + +  if (list == NULL) +    { +      g_warning ("Trying to disconnect a signal on a proxy but none are connected\n"); +      return; +    } + +  g_assert (g_slist_find (list->proxies, proxy) != NULL); +   +  list->proxies = g_slist_remove (list->proxies, proxy); + +  g_assert (g_slist_find (list->proxies, proxy) == NULL); +   +  UNLOCK_MANAGER (manager); +} + +static DBusHandlerResult +dbus_gproxy_manager_filter (DBusConnection    *connection, +                            DBusMessage       *message, +                            void              *user_data) +{ +  DBusGProxyManager *manager; +   +  manager = user_data; + +  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) +    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +  if (dbus_message_is_signal (message, +                              DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, +                              "Disconnected")) +    { +      /* FIXME g_object_run_dispose() all the proxies; should proxies have +       * a "destroy" signal? +       */ +    } +  else +    { +      char *tri; +      DBusGProxyList *list; +       +      tri = tristring_from_message (message); -static void dbus_gproxy_init        (DBusGProxy      *proxy); -static void dbus_gproxy_class_init  (DBusGProxyClass *klass); -static void dbus_gproxy_finalize    (GObject         *object); +      if (manager->proxy_lists) +        list = g_hash_table_lookup (manager->proxy_lists, tri); +      else +        list = NULL; + +      g_free (tri); +       +      if (list != NULL) +        { +          /* FIXME Emit the signal on each proxy in the list */ +           + +        } +    } +   +  /* "Handling" signals doesn't make sense, they are for everyone +   * who cares +   */ +  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + + + +/*      ---------- DBusGProxy --------------   */ + + + +enum +{ +  RECEIVED, +  LAST_SIGNAL +};  static void *parent_class; +static guint signals[LAST_SIGNAL] = { 0 };  static void  dbus_gproxy_init (DBusGProxy *proxy) @@ -179,6 +551,16 @@ dbus_gproxy_class_init (DBusGProxyClass *klass)    parent_class = g_type_class_peek_parent (klass);    object_class->finalize = dbus_gproxy_finalize; + +  signals[RECEIVED] = +    g_signal_new ("received", +		  G_OBJECT_CLASS_TYPE (object_class), +		  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, +                  0, +		  NULL, NULL, +                  g_cclosure_marshal_VOID__BOXED, +		  G_TYPE_NONE, 1, +                  DBUS_TYPE_MESSAGE);  }  static void @@ -189,7 +571,11 @@ dbus_gproxy_finalize (GObject *object)    proxy = DBUS_GPROXY (object);    if (proxy->manager) -    dbus_gproxy_manager_unref (proxy->manager); +    { +      dbus_gproxy_manager_unregister (proxy->manager, proxy); +      dbus_gproxy_manager_unref (proxy->manager); +    } +      g_free (proxy->service);    g_free (proxy->path);    g_free (proxy->interface); @@ -197,6 +583,53 @@ dbus_gproxy_finalize (GObject *object)    G_OBJECT_CLASS (parent_class)->finalize (object);  } +static char* +create_signal_detail (const char *interface, +                      const char *signal) +{ +  GString *str; + +  str = g_string_new (interface); + +  g_string_append (str, "."); + +  g_string_append (str, signal); + +  return g_string_free (str, FALSE); +} + +static void +dbus_gproxy_emit_received (DBusGProxy  *proxy, +                           DBusMessage *message) +{ +  const char *interface; +  const char *signal; +  char *detail; +  GQuark q; +   +  interface = dbus_message_get_interface (message); +  signal = dbus_message_get_member (message); + +  g_assert (interface != NULL); +  g_assert (signal != NULL); + +  detail = create_signal_detail (interface, signal); + +  /* If the quark isn't preexisting, there's no way there +   * are any handlers connected. We don't want to create +   * extra quarks for every possible signal. +   */ +  q = g_quark_try_string (detail); + +  if (q != 0) +    g_signal_emit (G_OBJECT (proxy), +                   signals[RECEIVED], +                   q, +                   message); + +  g_free (detail); +} +  /** @} End of DBusGLibInternals */  /** @addtogroup DBusGLib @@ -236,6 +669,33 @@ dbus_gproxy_get_type (void)    return object_type;  } +static DBusGProxy* +dbus_gproxy_new (DBusConnection *connection, +                 const char     *service_name, +                 const char     *path_name, +                 const char     *interface_name) +{ +  DBusGProxy *proxy; + +  g_assert (connection != NULL); +   +  proxy = g_object_new (DBUS_TYPE_GPROXY, NULL); + +  /* These should all be construct-only mandatory properties, +   * for now we just don't let people use g_object_new(). +   */ +   +  proxy->manager = dbus_gproxy_manager_get (connection); +   +  proxy->service = g_strdup (service_name); +  proxy->path = g_strdup (path_name); +  proxy->interface = g_strdup (interface_name); + +  dbus_gproxy_manager_register (proxy->manager, proxy); +   +  return proxy; +} +  /**   * Creates a new proxy for a remote interface. Method calls and signal   * connections over this proxy will go to the service owner; the @@ -267,17 +727,8 @@ dbus_gproxy_new_for_service (DBusConnection *connection,    g_return_val_if_fail (path_name != NULL, NULL);    g_return_val_if_fail (interface_name != NULL, NULL); -  proxy = g_object_new (DBUS_TYPE_GPROXY, NULL); - -  /* These should all be construct-only mandatory properties, -   * for now we just don't let people use g_object_new(). -   */ -   -  proxy->manager = dbus_gproxy_manager_get (connection); -   -  proxy->service = g_strdup (service_name); -  proxy->path = g_strdup (path_name); -  proxy->interface = g_strdup (interface_name); +  proxy = dbus_gproxy_new (connection, service_name, +                           path_name, interface_name);    return proxy;  } @@ -311,7 +762,7 @@ dbus_gproxy_begin_call (DBusGProxy *proxy,    DBusMessage *message;    va_list args; -  g_return_val_if_fail (proxy != NULL, NULL); +  g_return_val_if_fail (DBUS_IS_GPROXY (proxy), NULL);    message = dbus_message_new_method_call (proxy->service,                                            proxy->path, @@ -380,7 +831,7 @@ dbus_gproxy_end_call (DBusGProxy          *proxy,    va_list args;    DBusError derror; -  g_return_val_if_fail (proxy != NULL, FALSE); +  g_return_val_if_fail (DBUS_IS_GPROXY (proxy), FALSE);    g_return_val_if_fail (pending != NULL, FALSE);    dbus_pending_call_block (pending); @@ -406,6 +857,52 @@ dbus_gproxy_end_call (DBusGProxy          *proxy,  }  /** + * Sends a method call message as with dbus_gproxy_begin_call(), but + * does not ask for a reply or allow you to receive one. + * + * @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 first_arg_type type of the first argument + */ +void +dbus_gproxy_oneway_call (DBusGProxy               *proxy, +                         const char               *method, +                         int                       first_arg_type, +                         ...) +{ +  DBusMessage *message; +  va_list args; +   +  g_return_if_fail (DBUS_IS_GPROXY (proxy)); + +  message = dbus_message_new_method_call (proxy->service, +                                          proxy->path, +                                          proxy->interface, +                                          method); +  if (message == NULL) +    goto oom; + +  dbus_message_set_no_reply (message, TRUE); +   +  va_start (args, first_arg_type); +  if (!dbus_message_append_args_valist (message, first_arg_type, +                                        args)) +    goto oom; +  va_end (args); + +  if (!dbus_connection_send (proxy->manager->connection, +                             message, +                             NULL)) +    goto oom; + + oom: +  g_error ("Out of memory"); +} + +/**   * 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 @@ -428,7 +925,7 @@ dbus_gproxy_send (DBusGProxy          *proxy,                    DBusMessage         *message,                    dbus_uint32_t       *client_serial)  { -  g_return_if_fail (proxy != NULL); +  g_return_if_fail (DBUS_IS_GPROXY (proxy));    if (proxy->service)      { @@ -451,26 +948,62 @@ dbus_gproxy_send (DBusGProxy          *proxy,  }  void -dbus_gproxy_connect_signal (DBusGProxy       *proxy, -                            const char       *interface_name, -                            const char       *signal_name, -                            GCallback         callback, -                            void             *data, -                            GFreeFunc         free_data_func) +dbus_gproxy_connect_signal (DBusGProxy             *proxy, +                            const char             *signal_name, +                            DBusGProxySignalHandler handler, +                            void                   *data, +                            GFreeFunc               free_data_func)  { +  GClosure *closure; +  char *detail; +  g_return_if_fail (DBUS_IS_GPROXY (proxy)); +  g_return_if_fail (signal_name != NULL); +  g_return_if_fail (handler != NULL); +   +  detail = create_signal_detail (proxy->interface, signal_name); +   +  closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func); +  g_signal_connect_closure_by_id (G_OBJECT (proxy), +                                  signals[RECEIVED], +                                  g_quark_from_string (detail), +                                  closure, FALSE); +  g_free (detail);  }  void -dbus_gproxy_disconnect_signal (DBusGProxy       *proxy, -                               const char       *interface_name, -                               const char       *signal_name, -                               GCallback         callback, -                               void             *data) +dbus_gproxy_disconnect_signal (DBusGProxy             *proxy, +                               const char             *signal_name, +                               DBusGProxySignalHandler handler, +                               void                   *data)  { +  char *detail; +  GQuark q; -   +  g_return_if_fail (DBUS_IS_GPROXY (proxy)); +  g_return_if_fail (signal_name != NULL); +  g_return_if_fail (handler != NULL); + +  detail = create_signal_detail (proxy->interface, signal_name); +  q = g_quark_try_string (detail); +  g_free (detail); + +  if (q == 0) +    { +      g_warning ("%s: No signal handlers for %s found on this DBusGProxy", +                 G_GNUC_FUNCTION, signal_name); +      return; +    } + +  g_signal_handlers_disconnect_matched (G_OBJECT (proxy), +                                        G_SIGNAL_MATCH_DETAIL | +                                        G_SIGNAL_MATCH_FUNC   | +                                        G_SIGNAL_MATCH_DATA, +                                        signals[RECEIVED], +                                        q, +                                        NULL, +                                        G_CALLBACK (handler), data);  }  /** @} End of DBusGLib public */  | 
