diff options
| -rw-r--r-- | ChangeLog | 15 | ||||
| -rw-r--r-- | dbus/dbus-glib-lowlevel.h | 15 | ||||
| -rw-r--r-- | dbus/dbus-glib.h | 35 | ||||
| -rw-r--r-- | dbus/dbus-pending-call.c | 10 | ||||
| -rw-r--r-- | doc/TODO | 13 | ||||
| -rw-r--r-- | glib/dbus-glib.c | 335 | ||||
| -rw-r--r-- | glib/dbus-gmain.c | 172 | ||||
| -rw-r--r-- | glib/dbus-gproxy.c | 32 | ||||
| -rw-r--r-- | test/glib/test-dbus-glib.c | 5 | ||||
| -rw-r--r-- | tools/Makefile.am | 2 | ||||
| -rw-r--r-- | tools/dbus-names-model.c | 352 | ||||
| -rw-r--r-- | tools/dbus-names-model.h | 31 | ||||
| -rw-r--r-- | tools/dbus-tree-view.c | 13 | ||||
| -rw-r--r-- | tools/dbus-viewer.c | 110 | 
14 files changed, 838 insertions, 302 deletions
@@ -1,5 +1,20 @@  2005-01-30  Havoc Pennington  <hp@redhat.com> +	* glib/dbus-glib.c (dbus_g_pending_call_set_notify): new function +	(dbus_g_pending_call_cancel): new function + +	* dbus/dbus-glib.h: move GType decls for connection/message here; +	* dbus/dbus-glib.c: move all the g_type and ref/unref stuff in +	here, just kind of rationalizing how we handle all that + +	* tools/dbus-names-model.c: new file for a tree model listing the +	services on a bus + +	* tools/dbus-tree-view.c (model_new): use proper typing on the +	model rows + +2005-01-30  Havoc Pennington  <hp@redhat.com> +  	* glib/dbus-gmain.c: add a custom GSource back that just checks  	whether the message queue has anything in it; otherwise, there are   	cases where we won't see messages in the queue since there was no  diff --git a/dbus/dbus-glib-lowlevel.h b/dbus/dbus-glib-lowlevel.h index a689a926..94132151 100644 --- a/dbus/dbus-glib-lowlevel.h +++ b/dbus/dbus-glib-lowlevel.h @@ -32,15 +32,12 @@ G_BEGIN_DECLS  void dbus_set_g_error (GError   **gerror,                         DBusError *derror); -#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; - -#define DBUS_TYPE_G_CONNECTION (dbus_g_connection_get_g_type ()) -#define DBUS_TYPE_G_MESSAGE    (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; +#define DBUS_TYPE_CONNECTION      (dbus_connection_get_g_type ()) +#define DBUS_TYPE_MESSAGE         (dbus_message_get_g_type ()) +#define DBUS_TYPE_PENDING_CALL    (dbus_pending_call_get_g_type ()) +GType dbus_connection_get_g_type   (void) G_GNUC_CONST; +GType dbus_message_get_g_type      (void) G_GNUC_CONST; +GType dbus_pending_call_get_g_type (void) G_GNUC_CONST;  void            dbus_connection_setup_with_g_main (DBusConnection  *connection,                                                     GMainContext    *context); diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h index 3e73b98f..6c3c3c5f 100644 --- a/dbus/dbus-glib.h +++ b/dbus/dbus-glib.h @@ -34,11 +34,11 @@ G_BEGIN_DECLS  /** - * Convert to DBusConnection with dbus_g_connection_get_connection() + * Convert to DBusConnection with dbus_g_connection_get_connection() in dbus-glib-lowlevel.h   */  typedef struct DBusGConnection DBusGConnection;  /** - * Convert to DBusMessage with dbus_g_message_get_message() + * Convert to DBusMessage with dbus_g_message_get_message() in dbus-glib-lowlevel.h   */  typedef struct DBusGMessage DBusGMessage;  /** @@ -46,7 +46,33 @@ typedef struct DBusGMessage DBusGMessage;   */  typedef struct DBusGPendingCall DBusGPendingCall; -void dbus_g_connection_flush (DBusGConnection *connection); +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 () @@ -147,9 +173,6 @@ void              dbus_g_proxy_call_no_reply         (DBusGProxy        *proxy,                                                        ...);  const char*       dbus_g_proxy_get_bus_name          (DBusGProxy        *proxy); -DBusGPendingCall* dbus_g_pending_call_ref            (DBusGPendingCall  *call); -void              dbus_g_pending_call_unref          (DBusGPendingCall  *call); -  #undef DBUS_INSIDE_DBUS_GLIB_H  G_END_DECLS diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index d0403b03..b69f7c3e 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -227,11 +227,11 @@ dbus_pending_call_set_notify (DBusPendingCall              *pending,  }  /** - * Cancels the pending call, such that any reply - * or error received will just be ignored. - * Drops at least one reference to the #DBusPendingCall - * so will free the call if nobody else is holding - * a reference. + * Cancels the pending call, such that any reply or error received + * will just be ignored.  Drops the dbus library's internal reference + * to the #DBusPendingCall so will free the call if nobody else is + * holding a reference. However you usually get a reference + * from dbus_connection_send() so probably your app owns a ref also.   *    * @param pending the pending call   */ @@ -51,16 +51,9 @@ Important for 1.0 GLib Bindings   - finish dbus-glib-tool support for adding introspection      data to GObject and autoexporting GObject using same - - the GLib bindings varargs take DBUS_TYPE_WHATEVER and  -   return stuff allocated with dbus_malloc(); should this  -   be made more "G" at some expense in code duplication? -   You also still have to use some D-BUS functions such as  -   dbus_message_get_args() which takes a DBusError.  -   Probably we need to either fully encapsulate and hide  -   dbus/dbus.h, or encapsulate it slightly less e.g. no  -   GError. Or maybe it's as simple as "never return dbus_malloc()  -   memory" and just fully encapsulate the get_args() type of  -   stuff. + - Need to make sure that dbus-glib.h never returns any  +   dbus_malloc() memory, only g_malloc().  +   dbus_g_proxy_end_call() is the major offender.    - dbus_gproxy_connect_signal() has to take a signature for the signal      so it can figure out how to invoke the callback, or we have to rely diff --git a/glib/dbus-glib.c b/glib/dbus-glib.c index 4250a653..a8708736 100644 --- a/glib/dbus-glib.c +++ b/glib/dbus-glib.c @@ -47,6 +47,341 @@ dbus_g_connection_flush (DBusGConnection *connection)    dbus_connection_flush (DBUS_CONNECTION_FROM_G_CONNECTION (connection));  } +/** + * Increment refcount on a #DBusGConnection + *  + * @param connection the connection to ref + * @returns the connection that was ref'd + */ +DBusGConnection* +dbus_g_connection_ref (DBusGConnection *gconnection) +{ +  DBusConnection *c; + +  c = DBUS_CONNECTION_FROM_G_CONNECTION (gconnection); +  dbus_connection_ref (c); +  return gconnection; +} + + +/** + * Decrement refcount on a #DBusGConnection + *  + * @param connection the connection to unref + */ +void +dbus_g_connection_unref (DBusGConnection *gconnection) +{ +  DBusConnection *c; + +  c = DBUS_CONNECTION_FROM_G_CONNECTION (gconnection); +  dbus_connection_unref (c); +} + + +/** + * Increment refcount on a #DBusGMessage + *  + * @param message the message to ref + * @returns the message that was ref'd + */ +DBusGMessage* +dbus_g_message_ref (DBusGMessage *gmessage) +{ +  DBusMessage *c; + +  c = DBUS_MESSAGE_FROM_G_MESSAGE (gmessage); +  dbus_message_ref (c); +  return gmessage; +} + +/** + * Decrement refcount on a #DBusGMessage + *  + * @param message the message to unref + */ +void +dbus_g_message_unref (DBusGMessage *gmessage) +{ +  DBusMessage *c; + +  c = DBUS_MESSAGE_FROM_G_MESSAGE (gmessage); +  dbus_message_unref (c); +} + +/** + * 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. + * + * @returns the error domain quark for use with GError + */ +GQuark +dbus_g_error_quark (void) +{ +  static GQuark quark = 0; +  if (quark == 0) +    quark = g_quark_from_static_string ("g-exec-error-quark"); +  return quark; +} + + +/** + * Set a GError return location from a DBusError. + * + * @todo expand the DBUS_GERROR enum and take advantage of it here + *  + * @param gerror location to store a GError, or #NULL + * @param derror the DBusError + */ +void +dbus_set_g_error (GError   **gerror, +                  DBusError *derror) +{ +  g_return_if_fail (derror != NULL); +  g_return_if_fail (dbus_error_is_set (derror)); +   +  g_set_error (gerror, DBUS_GERROR, +               DBUS_GERROR_FAILED, +               _("D-BUS error %s: %s"), +               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; +} + +/** + * 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 + */ +GType +dbus_g_connection_get_g_type (void) +{ +  static GType our_type = 0; +   +  if (our_type == 0) +    our_type = g_boxed_type_register_static ("DBusGConnection", +                                             (GBoxedCopyFunc) dbus_g_connection_ref, +                                             (GBoxedFreeFunc) dbus_g_connection_unref); + +  return our_type; +} + +/** + * Get the GLib type ID for a DBusGMessage boxed type. + * + * @returns GLib type + */ +GType +dbus_g_message_get_g_type (void) +{ +  static GType our_type = 0; +   +  if (our_type == 0) +    our_type = g_boxed_type_register_static ("DBusGMessage", +                                             (GBoxedCopyFunc) dbus_g_message_ref, +                                             (GBoxedFreeFunc) dbus_g_message_unref); + +  return our_type; +} + +/** + * 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. + * + * @returns DBusConnection  + */ +DBusConnection* +dbus_g_connection_get_connection (DBusGConnection *gconnection) +{ +  return DBUS_CONNECTION_FROM_G_CONNECTION (gconnection); +} + +/** + * Get the DBusMessage corresponding to this DBusGMessage. + * The return value does not have its refcount incremented. + * + * @returns DBusMessage  + */ +DBusMessage* +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 */ diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 63e1d79e..4057482e 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -731,178 +731,6 @@ dbus_g_bus_get (DBusBusType     type,    return DBUS_G_CONNECTION_FROM_CONNECTION (connection);  } -/** - * The implementation of DBUS_GERROR error domain. See documentation - * for GError in GLib reference manual. - * - * @returns the error domain quark for use with GError - */ -GQuark -dbus_g_error_quark (void) -{ -  static GQuark quark = 0; -  if (quark == 0) -    quark = g_quark_from_static_string ("g-exec-error-quark"); -  return quark; -} - - -/** - * Set a GError return location from a DBusError. - * - * @todo expand the DBUS_GERROR enum and take advantage of it here - *  - * @param gerror location to store a GError, or #NULL - * @param derror the DBusError - */ -void -dbus_set_g_error (GError   **gerror, -                  DBusError *derror) -{ -  g_return_if_fail (derror != NULL); -  g_return_if_fail (dbus_error_is_set (derror)); -   -  g_set_error (gerror, DBUS_GERROR, -               DBUS_GERROR_FAILED, -               _("D-BUS error %s: %s"), -               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; -} - -static DBusGConnection* -dbus_g_connection_ref (DBusGConnection *gconnection) -{ -  DBusConnection *c; - -  c = DBUS_CONNECTION_FROM_G_CONNECTION (gconnection); -  dbus_connection_ref (c); -  return gconnection; -} - -static void -dbus_g_connection_unref (DBusGConnection *gconnection) -{ -  DBusConnection *c; - -  c = DBUS_CONNECTION_FROM_G_CONNECTION (gconnection); -  dbus_connection_unref (c); -} - - -static DBusGMessage* -dbus_g_message_ref (DBusGMessage *gmessage) -{ -  DBusMessage *c; - -  c = DBUS_MESSAGE_FROM_G_MESSAGE (gmessage); -  dbus_message_ref (c); -  return gmessage; -} - -static void -dbus_g_message_unref (DBusGMessage *gmessage) -{ -  DBusMessage *c; - -  c = DBUS_MESSAGE_FROM_G_MESSAGE (gmessage); -  dbus_message_unref (c); -} - -/** - * Get the GLib type ID for a DBusGConnection boxed type. - * - * @returns GLib type - */ -GType -dbus_g_connection_get_g_type (void) -{ -  static GType our_type = 0; -   -  if (our_type == 0) -    our_type = g_boxed_type_register_static ("DBusGConnection", -                                             (GBoxedCopyFunc) dbus_g_connection_ref, -                                             (GBoxedFreeFunc) dbus_g_connection_unref); - -  return our_type; -} - -/** - * Get the GLib type ID for a DBusGMessage boxed type. - * - * @returns GLib type - */ -GType -dbus_g_message_get_g_type (void) -{ -  static GType our_type = 0; -   -  if (our_type == 0) -    our_type = g_boxed_type_register_static ("DBusGMessage", -                                             (GBoxedCopyFunc) dbus_g_message_ref, -                                             (GBoxedFreeFunc) dbus_g_message_unref); - -  return our_type; -} - -/** - * Get the DBusConnection corresponding to this DBusGConnection. - * The return value does not have its refcount incremented. - * - * @returns DBusConnection  - */ -DBusConnection* -dbus_g_connection_get_connection (DBusGConnection *gconnection) -{ -  return DBUS_CONNECTION_FROM_G_CONNECTION (gconnection); -} - -/** - * Get the DBusMessage corresponding to this DBusGMessage. - * The return value does not have its refcount incremented. - * - * @returns DBusMessage  - */ -DBusMessage* -dbus_g_message_get_message (DBusGMessage *gmessage) -{ -  return DBUS_MESSAGE_FROM_G_MESSAGE (gmessage); -} -  /** @} */ /* end of public API */  #ifdef DBUS_BUILD_TESTS diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index 39f8ba86..c38c702d 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -1122,10 +1122,8 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy,   * 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_pending_call_set_notify() to be notified asynchronously that a - * pending call has been completed. Use - * dbus_pending_call_get_completed() to check whether a call has been - * completed. If it's completed, it will not block. + * 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.   *   * If the call results in an error, the error is set as normal for   * GError and the function returns #FALSE. @@ -1135,7 +1133,7 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy,   * The list should be terminated with #DBUS_TYPE_INVALID.   *   * This function doesn't affect the reference count of the - * #DBusPendingCall, the caller of dbus_g_proxy_begin_call() still owns + * #DBusGPendingCall, the caller of dbus_g_proxy_begin_call() still owns   * a reference.   *   * @todo this should be changed to make a g_malloc() copy of the @@ -1247,30 +1245,6 @@ dbus_g_proxy_call_no_reply (DBusGProxy               *proxy,  }  /** - * 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)); -} - -/**   * 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 diff --git a/test/glib/test-dbus-glib.c b/test/glib/test-dbus-glib.c index f217cf5e..5f565a0a 100644 --- a/test/glib/test-dbus-glib.c +++ b/test/glib/test-dbus-glib.c @@ -80,6 +80,11 @@ main (int argc, char **argv)        exit (1);      } +  /* should always get the same one */ +  g_assert (connection == dbus_g_bus_get (DBUS_BUS_SESSION, NULL)); +  g_assert (connection == dbus_g_bus_get (DBUS_BUS_SESSION, NULL)); +  g_assert (connection == dbus_g_bus_get (DBUS_BUS_SESSION, NULL)); +      /* Create a proxy object for the "bus driver" */    driver = dbus_g_proxy_new_for_name (connection, diff --git a/tools/Makefile.am b/tools/Makefile.am index d3accc88..b6747b0f 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -31,6 +31,8 @@ dbus_cleanup_sockets_SOURCES=			\  	dbus-cleanup-sockets.c  dbus_viewer_SOURCES=				\ +	dbus-names-model.c			\ +	dbus-names-model.h			\  	dbus-tree-view.c			\  	dbus-tree-view.h			\  	dbus-viewer.c diff --git a/tools/dbus-names-model.c b/tools/dbus-names-model.c new file mode 100644 index 00000000..09f1236d --- /dev/null +++ b/tools/dbus-names-model.c @@ -0,0 +1,352 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-names-model.c GtkTreeModel for names on the bus + * + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ +#include "dbus-names-model.h" +#include <glib/gi18n.h> + +enum +{ +  MODEL_COLUMN_NAME_DATA, +   +  MODEL_COLUMN_LAST +}; + +typedef struct +{ +  int   refcount; +  char *name; +} NameData; + +static NameData* +name_data_new (const char *name) +{ +  NameData *nd; + +  nd = g_new0 (NameData, 1); + +  nd->refcount = 1; +  nd->name = g_strdup (name); + +  return nd; +} + +static NameData* +name_data_ref (NameData *nd) +{ +  nd->refcount += 1; +  return nd; +} + +static void +name_data_unref (NameData *nd) +{ +  nd->refcount -= 1; +  if (nd->refcount == 0) +    { +      g_free (nd->name); +      g_free (nd); +    } +} + +static GType +name_data_get_gtype (void) +{ +  static GType our_type = 0; + +  if (our_type == 0) +    our_type = g_boxed_type_register_static ("NameData", +                                             (GBoxedCopyFunc) name_data_ref, +                                             (GBoxedFreeFunc) name_data_unref); + +  return our_type; +} + +#define NAME_DATA_TYPE (name_data_get_gtype()) + + +typedef struct NamesModel NamesModel; +typedef struct NamesModelClass NamesModelClass; + +GType names_model_get_type (void); + +struct NamesModel +{ +  GtkTreeStore parent; +  DBusGConnection *connection; +  DBusGProxy *driver_proxy; +  DBusGPendingCall *pending_list_names; +}; + +struct NamesModelClass +{ +  GtkTreeStoreClass parent; +}; + +#define TYPE_NAMES_MODEL              (names_model_get_type ()) +#define NAMES_MODEL(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_NAMES_MODEL, NamesModel)) +#define NAMES_MODEL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NAMES_MODEL, NamesModelClass)) +#define IS_NAMES_MODEL(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), TYPE_NAMES_MODEL)) +#define IS_NAMES_MODEL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NAMES_MODEL)) +#define NAMES_MODEL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NAMES_MODEL, NamesModelClass)) + +static void +have_names_notify (DBusGPendingCall *call, +                   void             *data) +{ +  NamesModel *names_model; +  GError *error; +  char **names; +  int n_elements; +  int i; + +  names_model = NAMES_MODEL (data); + +  g_assert (names_model->pending_list_names); +  g_assert (names_model->driver_proxy); + +  names = NULL; +  error = NULL; +  if (!dbus_g_proxy_end_call (names_model->driver_proxy, +                              names_model->pending_list_names, +                              &error, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, +                              &names, &n_elements, DBUS_TYPE_INVALID)) +    { +      g_assert (names == NULL); +      g_assert (error != NULL); +       +      g_printerr (_("Failed to load names on the bus: %s\n"), error->message); +      return; +    } + +  i = 0; +  while (names[i]) +    { +      NameData *nd; +      GtkTreeIter iter; +       +      nd = name_data_new (names[i]); + +      gtk_tree_store_append (GTK_TREE_STORE (names_model), +                             &iter, NULL); + +      gtk_tree_store_set (GTK_TREE_STORE (names_model), +                          &iter, +                          MODEL_COLUMN_NAME_DATA, nd, +                          -1); + +      name_data_unref (nd); +       +      ++i; +    } +   +  g_strfreev (names); +} + +static void +names_model_reload (NamesModel *names_model) +{ +  GtkTreeStore *tree_store; + +  tree_store = GTK_TREE_STORE (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); +      names_model->pending_list_names = NULL; +    } +   +  gtk_tree_store_clear (tree_store); +   +  if (names_model->connection == NULL) +    return; +   +  names_model->pending_list_names = +    dbus_g_proxy_begin_call (names_model->driver_proxy, +                             "ListNames", +                             DBUS_TYPE_INVALID); + +  dbus_g_pending_call_set_notify (names_model->pending_list_names, +                                  have_names_notify, names_model, NULL); +} + +static void +names_model_set_connection (NamesModel      *names_model, +                            DBusGConnection *connection) +{ +  const char *match_rule = "type='signal',member='NameOwnerChanged'"; + +  g_return_if_fail (IS_NAMES_MODEL (names_model)); +   +  if (connection == names_model->connection) +    return; + +  if (names_model->connection) +    { +      dbus_g_proxy_call_no_reply (names_model->driver_proxy, +                                  "RemoveMatch",  +                                  DBUS_TYPE_STRING, &match_rule, +                                  DBUS_TYPE_INVALID); +      g_object_unref (names_model->driver_proxy); +      names_model->driver_proxy = NULL; +      dbus_g_connection_unref (names_model->connection); +      names_model->connection = NULL; +    } +   +  if (connection) +    { +      names_model->connection = connection; +      dbus_g_connection_ref (names_model->connection); +       +      names_model->driver_proxy = +        dbus_g_proxy_new_for_name (names_model->connection, +                                   DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, +                                   DBUS_PATH_ORG_FREEDESKTOP_DBUS, +                                   DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS); +      g_assert (names_model->driver_proxy); +    } + +  names_model_reload (names_model); +} + +G_DEFINE_TYPE(NamesModel, names_model, GTK_TYPE_TREE_STORE) + +/* Properties */ +enum +{ +  PROP_0, +  PROP_CONNECTION +}; + +static void +names_model_dispose (GObject *object) +{ +  NamesModel *names_model = NAMES_MODEL (object); + +  names_model_set_connection (names_model, NULL); + +  g_assert (names_model->connection == NULL); +  g_assert (names_model->driver_proxy == NULL); +  g_assert (names_model->pending_list_names == NULL); + +  (G_OBJECT_CLASS (names_model_parent_class)->dispose) (object); +} + +static void +names_model_finalize (GObject *object) +{ +  NamesModel *names_model = NAMES_MODEL (object); + +  g_assert (names_model->connection == NULL); +  g_assert (names_model->driver_proxy == NULL); +  g_assert (names_model->pending_list_names == NULL); + +  (G_OBJECT_CLASS (names_model_parent_class)->finalize) (object); +} + +static void +names_model_set_property (GObject      *object, +                          guint         prop_id, +                          const GValue *value, +                          GParamSpec   *pspec) +{ +  NamesModel *names_model; + +  names_model = NAMES_MODEL (object); + +  switch (prop_id) +    { +    case PROP_CONNECTION: +      names_model_set_connection (names_model, g_value_get_boxed (value)); +      break; + +    default: +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +      break; +    } +} + +static void +names_model_get_property (GObject      *object, +                          guint         prop_id, +                          GValue       *value, +                          GParamSpec   *pspec) +{ +  NamesModel *names_model; + +  names_model = NAMES_MODEL (object); + +  switch (prop_id) +    { +    case PROP_CONNECTION: +      g_value_set_boxed (value, names_model->connection); +      break; + +    default: +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +      break; +    } +} + +static void +names_model_init (NamesModel *names_model) +{ +  GtkTreeStore *tree_store; +  GType types[MODEL_COLUMN_LAST]; + +  tree_store = GTK_TREE_STORE (names_model); + +  types[0] = NAME_DATA_TYPE; +  gtk_tree_store_set_column_types (tree_store, MODEL_COLUMN_LAST, types); +} + +static void +names_model_class_init (NamesModelClass *names_model_class) +{ +  GObjectClass *gobject_class = G_OBJECT_CLASS (names_model_class); + +  gobject_class->finalize = names_model_finalize; +  gobject_class->dispose = names_model_dispose; +  gobject_class->set_property = names_model_set_property; +  gobject_class->get_property = names_model_get_property; + +  g_object_class_install_property (gobject_class, +				   PROP_CONNECTION, +				   g_param_spec_boxed ("connection", +                                                       _("Bus connection"), +                                                       _("Connection to the message bus"), +                                                       DBUS_TYPE_G_CONNECTION, +                                                       G_PARAM_READWRITE)); +} + +GtkTreeModel* +names_model_new (DBusGConnection *connection) +{ +  NamesModel *names_model; + +  names_model = g_object_new (TYPE_NAMES_MODEL, +                              "connection", connection, +                              NULL); + +  return GTK_TREE_MODEL (names_model); +} + diff --git a/tools/dbus-names-model.h b/tools/dbus-names-model.h new file mode 100644 index 00000000..c2b54fc8 --- /dev/null +++ b/tools/dbus-names-model.h @@ -0,0 +1,31 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-names-model.h GtkTreeModel for names on the bus + * + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + *  + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + *  + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ +#ifndef DBUS_NAMES_MODEL_H +#define DBUS_NAMES_MODEL_H + +#include <gtk/gtk.h> +#include <dbus/dbus-glib.h> + +GtkTreeModel* names_model_new (DBusGConnection *connection); + +#endif /* DBUS_NAMES_MODEL_H */ diff --git a/tools/dbus-tree-view.c b/tools/dbus-tree-view.c index 7c52935e..d2898fb3 100644 --- a/tools/dbus-tree-view.c +++ b/tools/dbus-tree-view.c @@ -23,10 +23,7 @@  #include <string.h>  #include <config.h>  #include "dbus-tree-view.h" - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x +#include <glib/gi18n.h>  enum  { @@ -52,12 +49,7 @@ model_new (void)    GtkTreeStore *store;    store = gtk_tree_store_new (MODEL_COLUMN_LAST, -                              G_TYPE_POINTER); -  /* FIXME, BASE_INFO_TYPE doesn't work right (crashes), -   * G_TYPE_POINTER has a memleak. BASE_INFO_TYPE problem maybe just a -   * bad GTK build on my laptop. -   */ -  /* BASE_INFO_TYPE); */ +                              BASE_INFO_TYPE);    model = GTK_TREE_MODEL (store); @@ -114,7 +106,6 @@ set_info (GtkTreeModel *model,     */    if (root != NULL)      { -      base_info_ref (info); /* FIXME once boxed types are working */        gtk_tree_store_set (store, root,                            MODEL_COLUMN_INFO, info,                            -1); diff --git a/tools/dbus-viewer.c b/tools/dbus-viewer.c index abd299f6..524030c6 100644 --- a/tools/dbus-viewer.c +++ b/tools/dbus-viewer.c @@ -27,58 +27,19 @@  #include <string.h>  #include <gtk/gtk.h>  #include "dbus-tree-view.h" +#include "dbus-names-model.h"  #include <glib/dbus-gparser.h>  #include <glib/dbus-gutils.h>  #include <dbus/dbus-glib.h> - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x - -typedef struct -{ -  int refcount; -  char *name; - -} ServiceData; - -static ServiceData* -service_data_new (const char *name) -{ -  ServiceData *sd; - -  sd = g_new0 (ServiceData, 1); - -  sd->refcount = 1; -  sd->name = g_strdup (name); - -  return sd; -} - -static void -service_data_ref (ServiceData *sd) -{ -  sd->refcount += 1; -} - -static void -service_data_unref (ServiceData *sd) -{ -  sd->refcount -= 1; -  if (sd->refcount == 0) -    { -      g_free (sd->name); -      g_free (sd); -    } -} +#include <glib/gi18n.h>  typedef struct  {    GtkWidget *window;    GtkWidget *treeview; -  GtkWidget *service_menu; +  GtkWidget *name_menu; -  GSList *services; +  GtkTreeModel *names_model;  } TreeWindow; @@ -92,12 +53,14 @@ window_closed_callback (GtkWidget  *window,  }  static TreeWindow* -tree_window_new (void) +tree_window_new (DBusGConnection *connection, +                 GtkTreeModel    *names_model)  {    TreeWindow *w;    GtkWidget *sw;    GtkWidget *vbox;    GtkWidget *hbox; +  GtkWidget *combo;    /* Should use glade, blah */ @@ -117,6 +80,17 @@ tree_window_new (void)    hbox = gtk_hbox_new (FALSE, 6);    gtk_container_add (GTK_CONTAINER (vbox), hbox); + +  /* Create names option menu */ +  if (connection) +    { +      w->names_model = names_model; + +      combo = gtk_combo_box_new_with_model (w->names_model); + +      gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0); +    } +      /* Create tree view */    sw = gtk_scrolled_window_new (NULL, NULL); @@ -130,10 +104,6 @@ tree_window_new (void)    gtk_container_add (GTK_CONTAINER (sw), w->treeview); -  /* Create services option menu */ - -   -    /* Show everything */    gtk_widget_show_all (w->window); @@ -287,11 +257,11 @@ load_child_nodes (const char *service_name,  }  static NodeInfo* -load_from_service (const char *service_name, -                   GError    **error) +load_from_service (DBusGConnection *connection, +                   const char      *service_name, +                   GError         **error)  { -  DBusGConnection *connection; -  DBusGProxy *root_proxy; +   DBusGProxy *root_proxy;    DBusGPendingCall *call;    const char *data;    NodeInfo *node; @@ -300,11 +270,7 @@ load_from_service (const char *service_name,    node = NULL;    call = NULL;    path = NULL; -   -  connection = dbus_g_bus_get (DBUS_BUS_SESSION, error); -  if (connection == NULL) -    return NULL; - +   #if 1    /* this will end up autolaunching the service when we introspect it */    root_proxy = dbus_g_proxy_new_for_name (connection, @@ -396,6 +362,9 @@ main (int argc, char **argv)    gboolean end_of_args;    GSList *tmp;    gboolean services; +  DBusGConnection *connection; +  GError *error; +  GtkTreeModel *names_model;    bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR);    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); @@ -443,20 +412,41 @@ main (int argc, char **argv)        ++i;      } +  if (services) +    { +      error = NULL; +      connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); +      if (connection == NULL) +        { +          g_printerr ("Could not open bus connection: %s\n", +                      error->message); +          g_error_free (error); +          exit (1); +        } + +      g_assert (connection == dbus_g_bus_get (DBUS_BUS_SESSION, NULL)); + +      names_model = names_model_new (connection); +    } +  else +    { +      connection = NULL; +      names_model = NULL; +    } +      files = g_slist_reverse (files);    tmp = files;    while (tmp != NULL)      {        NodeInfo *node; -      GError *error;        const char *filename;        filename = tmp->data;        error = NULL;        if (services) -        node = load_from_service (filename, &error); +        node = load_from_service (connection, filename, &error);        else          node = description_load_from_file (filename,                                             &error); @@ -485,7 +475,7 @@ main (int argc, char **argv)            path = _dbus_gutils_split_path (name); -          w = tree_window_new ();           +          w = tree_window_new (connection, names_model);             dbus_tree_view_update (GTK_TREE_VIEW (w->treeview),                                   (const char**) path,                                   node);  | 
