summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-09-17 03:52:07 +0000
committerHavoc Pennington <hp@redhat.com>2003-09-17 03:52:07 +0000
commit583994cb3b7f5562fb7b8c37b4cb0d5af78e4ce2 (patch)
treed61f39d2ccb581f3a46d03f58bca93c2ac229afd
parent85ab0327d82e4945ad16630e583d8cc68df25a90 (diff)
downloaddbus-583994cb3b7f5562fb7b8c37b4cb0d5af78e4ce2.tar.gz
2003-09-15 Havoc Pennington <hp@pobox.com>
* dbus/dbus-pending-call.c: add the get/set object data boilerplate as for DBusConnection, etc. Use generic object data for the notify callback. * glib/dbus-gparser.c (parse_node): parse child nodes * tools/dbus-viewer.c: more hacking on the dbus-viewer * glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to contain functions shared between the convenience lib and the installed lib * glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add -export-symbols-regex to the GLib library * dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock): fix the locking in here, and add a default handler for Introspect() that just returns sub-nodes. 2003-09-14 Havoc Pennington <hp@pobox.com> * glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo rather than gfoo consistent * glib/dbus-gproxy.h: delete for now, move contents to dbus-glib.h, because the include files don't work right since we aren't in the dbus/ subdir. * glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing (dbus_gproxy_end_call): finish (dbus_gproxy_begin_call): finish * glib/dbus-gmain.c (dbus_set_g_error): new * glib/dbus-gobject.c (handle_introspect): include information about child nodes in the introspection * dbus/dbus-connection.c (dbus_connection_list_registered): new function to help in implementation of introspection * dbus/dbus-object-tree.c (_dbus_object_tree_list_registered_and_unlock): new function 2003-09-12 Havoc Pennington <hp@pobox.com> * glib/dbus-gidl.h: add common base class for all the foo_info types * tools/dbus-viewer.c: add GTK-based introspection UI thingy similar to kdcop * test/Makefile.am: try test srcdir -ef . in addition to test srcdir = ., one of them should work (yeah lame) * glib/Makefile.am: build the "idl" parser stuff as a convenience library * glib/dbus-gparser.h: make description_load routines return NodeInfo* not Parser* * Makefile.am (SUBDIRS): build test dir after all library dirs * configure.in: add GTK+ detection
-rw-r--r--ChangeLog66
-rw-r--r--Makefile.am2
-rw-r--r--configure.in30
-rw-r--r--dbus/dbus-connection-internal.h5
-rw-r--r--dbus/dbus-connection.c28
-rw-r--r--dbus/dbus-connection.h3
-rw-r--r--dbus/dbus-internals.h3
-rw-r--r--dbus/dbus-object-tree.c164
-rw-r--r--dbus/dbus-object-tree.h4
-rw-r--r--dbus/dbus-pending-call.c171
-rw-r--r--dbus/dbus-pending-call.h11
-rw-r--r--dbus/dbus-threads.c1
-rw-r--r--doc/TODO4
-rw-r--r--glib/Makefile.am29
-rw-r--r--glib/dbus-gidl.c226
-rw-r--r--glib/dbus-gidl.h26
-rw-r--r--glib/dbus-glib.h71
-rw-r--r--glib/dbus-gloader-expat.c19
-rw-r--r--glib/dbus-gmain.c41
-rw-r--r--glib/dbus-gobject.c89
-rw-r--r--glib/dbus-gparser.c8
-rw-r--r--glib/dbus-gparser.h10
-rw-r--r--glib/dbus-gproxy.c101
-rw-r--r--glib/dbus-gtest.c4
-rw-r--r--glib/dbus-gtest.h1
-rw-r--r--glib/dbus-gthread.c2
-rw-r--r--test/Makefile.am2
-rw-r--r--test/glib/test-profile.c2
-rw-r--r--test/glib/test-thread-client.c2
-rw-r--r--test/glib/test-thread-server.c2
-rw-r--r--tools/Makefile.am18
31 files changed, 944 insertions, 201 deletions
diff --git a/ChangeLog b/ChangeLog
index a4dba23f..caa4a754 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,69 @@
+2003-09-15 Havoc Pennington <hp@pobox.com>
+
+ * dbus/dbus-pending-call.c: add the get/set object data
+ boilerplate as for DBusConnection, etc. Use generic object data
+ for the notify callback.
+
+ * glib/dbus-gparser.c (parse_node): parse child nodes
+
+ * tools/dbus-viewer.c: more hacking on the dbus-viewer
+
+ * glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to
+ contain functions shared between the convenience lib and the
+ installed lib
+
+ * glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add
+ -export-symbols-regex to the GLib library
+
+ * dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock):
+ fix the locking in here, and add a default handler for
+ Introspect() that just returns sub-nodes.
+
+2003-09-14 Havoc Pennington <hp@pobox.com>
+
+ * glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo
+ rather than gfoo consistent
+
+ * glib/dbus-gproxy.h: delete for now, move contents to
+ dbus-glib.h, because the include files don't work right since we
+ aren't in the dbus/ subdir.
+
+ * glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing
+ (dbus_gproxy_end_call): finish
+ (dbus_gproxy_begin_call): finish
+
+ * glib/dbus-gmain.c (dbus_set_g_error): new
+
+ * glib/dbus-gobject.c (handle_introspect): include information
+ about child nodes in the introspection
+
+ * dbus/dbus-connection.c (dbus_connection_list_registered): new
+ function to help in implementation of introspection
+
+ * dbus/dbus-object-tree.c
+ (_dbus_object_tree_list_registered_and_unlock): new function
+
+2003-09-12 Havoc Pennington <hp@pobox.com>
+
+ * glib/dbus-gidl.h: add common base class for all the foo_info
+ types
+
+ * tools/dbus-viewer.c: add GTK-based introspection UI thingy
+ similar to kdcop
+
+ * test/Makefile.am: try test srcdir -ef . in addition to test
+ srcdir = ., one of them should work (yeah lame)
+
+ * glib/Makefile.am: build the "idl" parser stuff as a convenience
+ library
+
+ * glib/dbus-gparser.h: make description_load routines return
+ NodeInfo* not Parser*
+
+ * Makefile.am (SUBDIRS): build test dir after all library dirs
+
+ * configure.in: add GTK+ detection
+
2003-09-07 Havoc Pennington <hp@pobox.com>
* Make Doxygen contented.
diff --git a/Makefile.am b/Makefile.am
index 7384af0d..5bb5ae6a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,7 +17,7 @@ if DBUS_USE_MCS
endif
-SUBDIRS=dbus bus test doc $(GLIB_SUBDIR) $(GCJ_SUBDIR) $(MONO_SUBDIR) $(QT_SUBDIR) tools
+SUBDIRS=dbus bus doc $(GLIB_SUBDIR) $(GCJ_SUBDIR) $(MONO_SUBDIR) $(QT_SUBDIR) test tools
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = dbus-1.pc $(GLIB_PC)
diff --git a/configure.in b/configure.in
index c403fd8c..e81a8d6a 100644
--- a/configure.in
+++ b/configure.in
@@ -24,6 +24,7 @@ AC_HEADER_STDC
AC_ARG_ENABLE(qt, [ --enable-qt enable Qt-friendly client library],enable_qt=$enableval,enable_qt=auto)
AC_ARG_ENABLE(glib, [ --enable-glib enable GLib-friendly client library],enable_glib=$enableval,enable_glib=auto)
+AC_ARG_ENABLE(gtk, [ --enable-gtk enable GTK-requiring executables],enable_gtk=$enableval,enable_gtk=auto)
AC_ARG_ENABLE(tests, [ --enable-tests enable unit test code],enable_tests=$enableval,enable_tests=$USE_MAINTAINER_MODE)
AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
@@ -577,6 +578,34 @@ DBUS_GLIB_TOOL_LIBS=$XML_LIBS
AC_SUBST(DBUS_GLIB_TOOL_CFLAGS)
AC_SUBST(DBUS_GLIB_TOOL_LIBS)
+# GTK detection
+if test x$have_glib = xno ; then
+ AC_MSG_WARN([Can't use GTK+ since GLib not enabled])
+ have_gtk=no
+else
+ PKG_CHECK_MODULES(DBUS_GTK, gtk+-2.0, have_gtk=yes, have_gtk=no)
+fi
+
+if test x$have_gtk = xno ; then
+ AC_MSG_WARN([GTK+ development libraries not found])
+fi
+
+if test x$enable_gtk = xyes; then
+ if test x$have_gtk = xno; then
+ AC_MSG_ERROR([GTK+ explicitly required, and GTK+ development libraries not found])
+ fi
+fi
+
+if test x$enable_gtk = xno; then
+ have_gtk=no;
+fi
+
+AM_CONDITIONAL(HAVE_GTK, test x$have_gtk = xyes)
+
+dnl Gtk flags
+AC_SUBST(DBUS_GTK_CFLAGS)
+AC_SUBST(DBUS_GTK_LIBS)
+
# Qt detection
have_qt=no
AC_MSG_CHECKING([for qglobal.h])
@@ -885,6 +914,7 @@ echo "
Building checks: ${enable_checks}
Building Qt bindings: ${have_qt}
Building GLib bindings: ${have_glib}
+ Building GTK+ tools: ${have_gtk}
Building X11 code: ${enable_x11}
Building documentation: ${enable_docs}
Using XML parser: ${with_xml}
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index 5a04dece..b19ab636 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -30,6 +30,7 @@
#include <dbus/dbus-resources.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-timeout.h>
+#include <dbus/dbus-dataslot.h>
DBUS_BEGIN_DECLS;
@@ -104,9 +105,9 @@ struct DBusPendingCall
{
DBusAtomic refcount; /**< reference count */
+ DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
+
DBusPendingCallNotifyFunction function; /**< Notifier when reply arrives. */
- void *user_data; /**< user data for function */
- DBusFreeFunction free_user_data; /**< free the user data */
DBusConnection *connection; /**< Connections we're associated with */
DBusMessage *reply; /**< Reply (after we've received it) */
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index bab6ffd8..b55f270c 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -3101,7 +3101,6 @@ dbus_connection_register_object_path (DBusConnection *connection,
* path. You can use this to establish a default message handling
* policy for a whole "subdirectory."
*
- *
* @param connection the connection
* @param path #NULL-terminated array of path elements
* @param vtable the virtual table
@@ -3136,6 +3135,7 @@ dbus_connection_register_fallback (DBusConnection *connection,
/**
* Unregisters the handler registered with exactly the given path.
* It's a bug to call this function for a path that isn't registered.
+ * Can unregister both fallback paths and object paths.
*
* @param connection the connection
* @param path the #NULL-terminated array of path elements
@@ -3154,6 +3154,32 @@ dbus_connection_unregister_object_path (DBusConnection *connection,
path);
}
+/**
+ * Lists the registered fallback handlers and object path handlers at
+ * the given parent_path. The returned array should be freed with
+ * dbus_free_string_array().
+ *
+ * @param connection the connection
+ * @param parent_path the path to list the child handlers of
+ * @param child_entries returns #NULL-terminated array of children
+ * @returns #FALSE if no memory to allocate the child entries
+ */
+dbus_bool_t
+dbus_connection_list_registered (DBusConnection *connection,
+ const char **parent_path,
+ char ***child_entries)
+{
+ _dbus_return_val_if_fail (connection != NULL, FALSE);
+ _dbus_return_val_if_fail (parent_path != NULL, FALSE);
+ _dbus_return_val_if_fail (child_entries != NULL, FALSE);
+
+ CONNECTION_LOCK (connection);
+
+ return _dbus_object_tree_list_registered_and_unlock (connection->objects,
+ parent_path,
+ child_entries);
+}
+
static DBusDataSlotAllocator slot_allocator;
_DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h
index abc88056..a4212c74 100644
--- a/dbus/dbus-connection.h
+++ b/dbus/dbus-connection.h
@@ -240,6 +240,9 @@ dbus_bool_t dbus_connection_register_fallback (DBusConnection
void dbus_connection_unregister_object_path (DBusConnection *connection,
const char **path);
+dbus_bool_t dbus_connection_list_registered (DBusConnection *connection,
+ const char **parent_path,
+ char ***child_entries);
DBUS_END_DECLS;
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index 06a011e3..b3010355 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -230,13 +230,14 @@ extern int _dbus_current_generation;
_DBUS_DECLARE_GLOBAL_LOCK (list);
_DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
+_DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots);
_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
_DBUS_DECLARE_GLOBAL_LOCK (message_slots);
_DBUS_DECLARE_GLOBAL_LOCK (atomic);
_DBUS_DECLARE_GLOBAL_LOCK (bus);
_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
_DBUS_DECLARE_GLOBAL_LOCK (system_users);
-#define _DBUS_N_GLOBAL_LOCKS (8)
+#define _DBUS_N_GLOBAL_LOCKS (9)
dbus_bool_t _dbus_threads_init_debug (void);
diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c
index 9922dec4..07d3ae59 100644
--- a/dbus/dbus-object-tree.c
+++ b/dbus/dbus-object-tree.c
@@ -25,6 +25,7 @@
#include "dbus-internals.h"
#include "dbus-hash.h"
#include "dbus-protocol.h"
+#include "dbus-string.h"
#include <string.h>
#include <stdlib.h>
@@ -34,13 +35,7 @@
* @brief DBusObjectTree is used by DBusConnection to track the object tree
*
* Types and functions related to DBusObjectTree. These
- * are all internal.
- *
- * @todo this is totally broken, because of the following case:
- * /foo, /foo/bar, /foo/baz
- * if we then receive a message to /foo/baz we need to hand it
- * to /foo/baz and /foo but not /foo/bar. So we should be
- * using a real tree structure as with GConfListeners.
+ * are all library-internal.
*
* @{
*/
@@ -542,6 +537,101 @@ _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree)
tree->root = NULL;
}
+static dbus_bool_t
+_dbus_object_tree_list_registered_unlocked (DBusObjectTree *tree,
+ const char **parent_path,
+ char ***child_entries)
+{
+ DBusObjectSubtree *subtree;
+ char **retval;
+
+ _dbus_assert (parent_path != NULL);
+ _dbus_assert (child_entries != NULL);
+
+ *child_entries = NULL;
+
+ subtree = find_subtree (tree, parent_path, NULL);
+ if (subtree == NULL)
+ {
+ retval = dbus_new0 (char *, 1);
+ if (retval == NULL)
+ goto out;
+ }
+ else
+ {
+ int i;
+ retval = dbus_new0 (char*, subtree->n_subtrees + 1);
+ if (retval == NULL)
+ goto out;
+ i = 0;
+ while (i < subtree->n_subtrees)
+ {
+ retval[i] = _dbus_strdup (subtree->subtrees[i]->name);
+ if (retval[i] == NULL)
+ {
+ dbus_free_string_array (retval);
+ retval = NULL;
+ goto out;
+ }
+ ++i;
+ }
+ }
+
+ out:
+
+ *child_entries = retval;
+ return retval != NULL;
+}
+
+static DBusHandlerResult
+handle_default_introspect_unlocked (DBusObjectTree *tree,
+ DBusMessage *message,
+ const char **path)
+{
+ DBusString xml;
+ DBusHandlerResult result;
+ char **children;
+ int i;
+
+ if (!dbus_message_is_method_call (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE,
+ "Introspect"))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (!_dbus_string_init (&xml))
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ children = NULL;
+ if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children))
+ goto out;
+
+ if (!_dbus_string_append (&xml, "<node>\n"))
+ goto out;
+
+ i = 0;
+ while (children[i] != NULL)
+ {
+ if (!_dbus_string_append_printf (&xml, " <node name=\"%s\"/>\n",
+ children[i]))
+ goto out;
+
+ ++i;
+ }
+
+ if (!_dbus_string_append (&xml, "</node>\n"))
+ goto out;
+
+ result = DBUS_HANDLER_RESULT_HANDLED;
+
+ out:
+ _dbus_string_free (&xml);
+ dbus_free_string_array (children);
+
+ return result;
+}
+
/**
* Tries to dispatch a message by directing it to handler for the
* object path listed in the message header, if any. Messages are
@@ -572,12 +662,23 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
path = NULL;
if (!dbus_message_get_path_decomposed (message, &path))
{
+#ifdef DBUS_BUILD_TESTS
+ if (tree->connection)
+#endif
+ _dbus_connection_unlock (tree->connection);
+
_dbus_verbose ("No memory to get decomposed path\n");
+
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
if (path == NULL)
{
+#ifdef DBUS_BUILD_TESTS
+ if (tree->connection)
+#endif
+ _dbus_connection_unlock (tree->connection);
+
_dbus_verbose ("No path field in message\n");
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -649,30 +750,40 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
message,
user_data);
- if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
- goto free_and_return;
-
#ifdef DBUS_BUILD_TESTS
if (tree->connection)
#endif
_dbus_connection_lock (tree->connection);
+
+ if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+ goto free_and_return;
}
link = next;
}
+ free_and_return:
+
+ if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+ {
+ /* This hardcoded default handler does a minimal Introspect()
+ */
+ result = handle_default_introspect_unlocked (tree, message,
+ (const char**) path);
+ }
+
#ifdef DBUS_BUILD_TESTS
if (tree->connection)
#endif
_dbus_connection_unlock (tree->connection);
-
- free_and_return:
+
while (list != NULL)
{
link = _dbus_list_get_first_link (&list);
_dbus_object_subtree_unref (link->data);
_dbus_list_remove_link (&list, link);
}
+
dbus_free_string_array (path);
return result;
@@ -770,6 +881,35 @@ _dbus_object_subtree_unref (DBusObjectSubtree *subtree)
}
}
+/**
+ * Lists the registered fallback handlers and object path handlers at
+ * the given parent_path. The returned array should be freed with
+ * dbus_free_string_array().
+ *
+ * @param connection the connection
+ * @param parent_path the path to list the child handlers of
+ * @param child_entries returns #NULL-terminated array of children
+ * @returns #FALSE if no memory to allocate the child entries
+ */
+dbus_bool_t
+_dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree,
+ const char **parent_path,
+ char ***child_entries)
+{
+ dbus_bool_t result;
+
+ result = _dbus_object_tree_list_registered_unlocked (tree,
+ parent_path,
+ child_entries);
+
+#ifdef DBUS_BUILD_TESTS
+ if (tree->connection)
+#endif
+ _dbus_connection_unlock (tree->connection);
+
+ return result;
+}
+
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-object-tree.h b/dbus/dbus-object-tree.h
index 21d8b5f1..bf34d972 100644
--- a/dbus/dbus-object-tree.h
+++ b/dbus/dbus-object-tree.h
@@ -44,7 +44,9 @@ DBusHandlerResult _dbus_object_tree_dispatch_and_unlock (DBusObjectTree
DBusMessage *message);
void _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree);
-
+dbus_bool_t _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree,
+ const char **parent_path,
+ char ***child_entries);
DBUS_END_DECLS;
#endif /* DBUS_OBJECT_TREE_H */
diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c
index 2b6021e9..dad444e3 100644
--- a/dbus/dbus-pending-call.c
+++ b/dbus/dbus-pending-call.c
@@ -38,6 +38,8 @@
* @{
*/
+static dbus_int32_t notify_user_data_slot = -1;
+
/**
* Creates a new pending reply object.
*
@@ -58,11 +60,17 @@ _dbus_pending_call_new (DBusConnection *connection,
if (timeout_milliseconds == -1)
timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
+
+ if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot))
+ return NULL;
pending = dbus_new (DBusPendingCall, 1);
if (pending == NULL)
- return NULL;
+ {
+ dbus_pending_call_free_data_slot (&notify_user_data_slot);
+ return NULL;
+ }
timeout = _dbus_timeout_new (timeout_milliseconds,
timeout_handler,
@@ -70,6 +78,7 @@ _dbus_pending_call_new (DBusConnection *connection,
if (timeout == NULL)
{
+ dbus_pending_call_free_data_slot (&notify_user_data_slot);
dbus_free (pending);
return NULL;
}
@@ -77,6 +86,8 @@ _dbus_pending_call_new (DBusConnection *connection,
pending->refcount.value = 1;
pending->connection = connection;
pending->timeout = timeout;
+
+ _dbus_data_slot_list_init (&pending->slot_list);
return pending;
}
@@ -94,7 +105,13 @@ _dbus_pending_call_notify (DBusPendingCall *pending)
pending->completed = TRUE;
if (pending->function)
- (* pending->function) (pending, pending->user_data);
+ {
+ void *user_data;
+ user_data = dbus_pending_call_get_data (pending,
+ notify_user_data_slot);
+
+ (* pending->function) (pending, user_data);
+ }
}
/** @} */
@@ -154,9 +171,8 @@ dbus_pending_call_unref (DBusPendingCall *pending)
_dbus_assert (!pending->timeout_added);
/* this assumes we aren't holding connection lock... */
- if (pending->free_user_data)
- (* pending->free_user_data) (pending->user_data);
-
+ _dbus_data_slot_list_free (&pending->slot_list);
+
if (pending->timeout != NULL)
_dbus_timeout_unref (pending->timeout);
@@ -174,6 +190,8 @@ dbus_pending_call_unref (DBusPendingCall *pending)
}
dbus_free (pending);
+
+ dbus_pending_call_free_data_slot (&notify_user_data_slot);
}
}
@@ -185,28 +203,24 @@ dbus_pending_call_unref (DBusPendingCall *pending)
* @param function notifier function
* @param user_data data to pass to notifier function
* @param free_user_data function to free the user data
- *
+ * @returns #FALSE if not enough memory
*/
-void
+dbus_bool_t
dbus_pending_call_set_notify (DBusPendingCall *pending,
DBusPendingCallNotifyFunction function,
void *user_data,
DBusFreeFunction free_user_data)
{
- DBusFreeFunction old_free_func;
- void *old_user_data;
-
- _dbus_return_if_fail (pending != NULL);
+ _dbus_return_val_if_fail (pending != NULL, FALSE);
- old_free_func = pending->free_user_data;
- old_user_data = pending->user_data;
-
- pending->user_data = user_data;
- pending->free_user_data = free_user_data;
+ /* could invoke application code! */
+ if (!dbus_pending_call_set_data (pending, notify_user_data_slot,
+ user_data, free_user_data))
+ return FALSE;
+
pending->function = function;
- if (old_free_func)
- (* old_free_func) (old_user_data);
+ return TRUE;
}
/**
@@ -230,9 +244,10 @@ dbus_pending_call_cancel (DBusPendingCall *pending)
* Checks whether the pending call has received a reply
* yet, or not.
*
+ * @todo not thread safe? I guess it has to lock though it sucks
+ *
* @param pending the pending call
- * @returns #TRUE if a reply has been received
- */
+ * @returns #TRUE if a reply has been received */
dbus_bool_t
dbus_pending_call_get_completed (DBusPendingCall *pending)
{
@@ -245,6 +260,9 @@ dbus_pending_call_get_completed (DBusPendingCall *pending)
* have to keep a reference count on the pending call (or add one
* to the message).
*
+ * @todo not thread safe? I guess it has to lock though it sucks
+ * @todo maybe to make this threadsafe, it should be steal_reply(), i.e. only one thread can ever get the message
+ *
* @param pending the pending call
* @returns the reply message or #NULL.
*/
@@ -260,6 +278,9 @@ dbus_pending_call_get_reply (DBusPendingCall *pending)
* main loop or process other messages, it simply waits for the reply
* in question.
*
+ * If the pending call is already completed, this function returns
+ * immediately.
+ *
* @todo when you start blocking, the timeout is reset, but it should
* really only use time remaining since the pending call was created.
*
@@ -269,6 +290,9 @@ void
dbus_pending_call_block (DBusPendingCall *pending)
{
DBusMessage *message;
+
+ if (dbus_pending_call_get_completed (pending))
+ return;
message = _dbus_connection_block_for_reply (pending->connection,
pending->reply_serial,
@@ -279,6 +303,113 @@ dbus_pending_call_block (DBusPendingCall *pending)
dbus_message_unref (message);
}
+static DBusDataSlotAllocator slot_allocator;
+_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
+
+/**
+ * Allocates an integer ID to be used for storing application-specific
+ * data on any DBusPendingCall. The allocated ID may then be used
+ * with dbus_pending_call_set_data() and dbus_pending_call_get_data().
+ * The passed-in slot must be initialized to -1, and is filled in
+ * with the slot ID. If the passed-in slot is not -1, it's assumed
+ * to be already allocated, and its refcount is incremented.
+ *
+ * The allocated slot is global, i.e. all DBusPendingCall objects will
+ * have a slot with the given integer ID reserved.
+ *
+ * @param slot_p address of a global variable storing the slot
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
+{
+ return _dbus_data_slot_allocator_alloc (&slot_allocator,
+ _DBUS_LOCK_NAME (pending_call_slots),
+ slot_p);
+}
+
+/**
+ * Deallocates a global ID for #DBusPendingCall data slots.
+ * dbus_pending_call_get_data() and dbus_pending_call_set_data() may
+ * no longer be used with this slot. Existing data stored on existing
+ * DBusPendingCall objects will be freed when the #DBusPendingCall is
+ * finalized, but may not be retrieved (and may only be replaced if
+ * someone else reallocates the slot). When the refcount on the
+ * passed-in slot reaches 0, it is set to -1.
+ *
+ * @param slot_p address storing the slot to deallocate
+ */
+void
+dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
+{
+ _dbus_return_if_fail (*slot_p >= 0);
+
+ _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
+}
+
+/**
+ * Stores a pointer on a #DBusPendingCall, along
+ * with an optional function to be used for freeing
+ * the data when the data is set again, or when
+ * the pending call is finalized. The slot number
+ * must have been allocated with dbus_pending_call_allocate_data_slot().
+ *
+ * @param pending the pending_call
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+dbus_pending_call_set_data (DBusPendingCall *pending,
+ dbus_int32_t slot,
+ void *data,
+ DBusFreeFunction free_data_func)
+{
+ DBusFreeFunction old_free_func;
+ void *old_data;
+ dbus_bool_t retval;
+
+ _dbus_return_val_if_fail (pending != NULL, FALSE);
+ _dbus_return_val_if_fail (slot >= 0, FALSE);
+
+ retval = _dbus_data_slot_list_set (&slot_allocator,
+ &pending->slot_list,
+ slot, data, free_data_func,
+ &old_free_func, &old_data);
+
+ if (retval)
+ {
+ if (old_free_func)
+ (* old_free_func) (old_data);
+ }
+
+ return retval;
+}
+
+/**
+ * Retrieves data previously set with dbus_pending_call_set_data().
+ * The slot must still be allocated (must not have been freed).
+ *
+ * @param pending the pending_call
+ * @param slot the slot to get data from
+ * @returns the data, or #NULL if not found
+ */
+void*
+dbus_pending_call_get_data (DBusPendingCall *pending,
+ dbus_int32_t slot)
+{
+ void *res;
+
+ _dbus_return_val_if_fail (pending != NULL, NULL);
+
+ res = _dbus_data_slot_list_get (&slot_allocator,
+ &pending->slot_list,
+ slot);
+
+ return res;
+}
+
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-pending-call.h b/dbus/dbus-pending-call.h
index 81af872f..4f1e92c0 100644
--- a/dbus/dbus-pending-call.h
+++ b/dbus/dbus-pending-call.h
@@ -35,7 +35,7 @@ DBUS_BEGIN_DECLS;
void dbus_pending_call_ref (DBusPendingCall *pending);
void dbus_pending_call_unref (DBusPendingCall *pending);
-void dbus_pending_call_set_notify (DBusPendingCall *pending,
+dbus_bool_t dbus_pending_call_set_notify (DBusPendingCall *pending,
DBusPendingCallNotifyFunction function,
void *user_data,
DBusFreeFunction free_user_data);
@@ -44,6 +44,15 @@ dbus_bool_t dbus_pending_call_get_completed (DBusPendingCall *pen
DBusMessage* dbus_pending_call_get_reply (DBusPendingCall *pending);
void dbus_pending_call_block (DBusPendingCall *pending);
+dbus_bool_t dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p);
+void dbus_pending_call_free_data_slot (dbus_int32_t *slot_p);
+dbus_bool_t dbus_pending_call_set_data (DBusPendingCall *pending,
+ dbus_int32_t slot,
+ void *data,
+ DBusFreeFunction free_data_func);
+void* dbus_pending_call_get_data (DBusPendingCall *pending,
+ dbus_int32_t slot);
+
DBUS_END_DECLS;
#endif /* DBUS_PENDING_CALL_H */
diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
index c5ce638f..2170c465 100644
--- a/dbus/dbus-threads.c
+++ b/dbus/dbus-threads.c
@@ -223,6 +223,7 @@ init_global_locks (void)
#define LOCK_ADDR(name) (& _dbus_lock_##name)
LOCK_ADDR (list),
LOCK_ADDR (connection_slots),
+ LOCK_ADDR (pending_call_slots),
LOCK_ADDR (server_slots),
LOCK_ADDR (message_slots),
LOCK_ADDR (atomic),
diff --git a/doc/TODO b/doc/TODO
index 6b308d39..5c2b149c 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -82,3 +82,7 @@
- Nuke the org.freedesktop.Broadcast service; instead,
just broadcast messages of type signal
+
+ - I don't want to introduce DBusObject, but refcounting and object
+ data could still be factored out into an internal "base class"
+ perhaps.
diff --git a/glib/Makefile.am b/glib/Makefile.am
index 65d71cfd..a45aa593 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -5,8 +5,7 @@ dbusincludedir=$(includedir)/dbus-1.0/dbus
lib_LTLIBRARIES=libdbus-glib-1.la
dbusinclude_HEADERS= \
- dbus-glib.h \
- dbus-gproxy.h
+ dbus-glib.h
libdbus_glib_1_la_SOURCES = \
dbus-gmain.c \
@@ -14,23 +13,36 @@ libdbus_glib_1_la_SOURCES = \
dbus-gproxy.c \
dbus-gtest.c \
dbus-gtest.h \
- dbus-gthread.c
+ dbus-gthread.c \
+ dbus-gutils.c \
+ dbus-gutils.h
libdbus_glib_1_la_LIBADD= $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la
+## don't export symbols that start with "_" (we use this
+## convention for internal symbols)
+libdbus_glib_1_la_LDFLAGS= -export-symbols-regex "^[^_].*"
-bin_PROGRAMS=dbus-glib-tool
+# convenience lib used here and by dbus-viewer
+noinst_LTLIBRARIES=libdbus-gtool.la
-dbus_glib_tool_SOURCES = \
+libdbus_gtool_la_SOURCES = \
dbus-gidl.c \
dbus-gidl.h \
- dbus-glib-tool.c \
dbus-gloader-expat.c \
dbus-gparser.c \
dbus-gparser.h \
- dbus-gtool-test.h
+ dbus-gutils.c \
+ dbus-gutils.h
+libdbus_gtool_la_LIBADD = libdbus-glib-1.la
-dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-glib-1.la $(top_builddir)/dbus/libdbus-1.la
+bin_PROGRAMS=dbus-glib-tool
+
+dbus_glib_tool_SOURCES = \
+ dbus-glib-tool.c \
+ dbus-gtool-test.h
+
+dbus_glib_tool_LDADD= $(DBUS_GLIB_TOOL_LIBS) libdbus-gtool.la
if DBUS_BUILD_TESTS
@@ -54,3 +66,4 @@ else
TESTS=
endif
+
diff --git a/glib/dbus-gidl.c b/glib/dbus-gidl.c
index b867d178..596b43ca 100644
--- a/glib/dbus-gidl.c
+++ b/glib/dbus-gidl.c
@@ -26,43 +26,131 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS
-struct NodeInfo
+struct BaseInfo
{
- int refcount;
+ unsigned int refcount : 28;
+ unsigned int type : 4;
char *name;
+};
+
+struct NodeInfo
+{
+ BaseInfo base;
GSList *interfaces;
+ GSList *nodes;
};
struct InterfaceInfo
{
- int refcount;
- char *name;
+ BaseInfo base;
+ /* Since we have BaseInfo now these could be one list */
GSList *methods;
GSList *signals;
};
struct MethodInfo
{
- int refcount;
+ BaseInfo base;
GSList *args;
- char *name;
};
struct SignalInfo
{
- int refcount;
+ BaseInfo base;
GSList *args;
- char *name;
};
struct ArgInfo
{
- int refcount;
- char *name;
+ BaseInfo base;
int type;
ArgDirection direction;
};
+void
+base_info_ref (BaseInfo *info)
+{
+ g_return_if_fail (info != NULL);
+ g_return_if_fail (info->refcount > 0);
+
+ info->refcount += 1;
+}
+
+static void
+base_info_free (void *ptr)
+{
+ BaseInfo *info;
+
+ info = ptr;
+
+ g_free (info->name);
+ g_free (info);
+}
+
+void
+base_info_unref (BaseInfo *info)
+{
+ g_return_if_fail (info != NULL);
+ g_return_if_fail (info->refcount > 0);
+
+ /* This is sort of bizarre, BaseInfo was tacked on later */
+
+ switch (info->type)
+ {
+ case INFO_TYPE_NODE:
+ node_info_unref ((NodeInfo*) info);
+ break;
+ case INFO_TYPE_INTERFACE:
+ interface_info_unref ((InterfaceInfo*) info);
+ break;
+ case INFO_TYPE_SIGNAL:
+ signal_info_unref ((SignalInfo*) info);
+ break;
+ case INFO_TYPE_METHOD:
+ method_info_unref ((MethodInfo*) info);
+ break;
+ case INFO_TYPE_ARG:
+ arg_info_unref ((ArgInfo*) info);
+ break;
+ }
+}
+
+InfoType
+base_info_get_type (BaseInfo *info)
+{
+ return info->type;
+}
+
+const char*
+base_info_get_name (BaseInfo *info)
+{
+ return info->name;
+}
+
+void
+base_info_set_name (BaseInfo *info,
+ const char *name)
+{
+ char *old;
+
+ old = info->name;
+ info->name = g_strdup (name);
+ g_free (old);
+}
+
+GType
+base_info_get_gtype (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("BaseInfo",
+ (GBoxedCopyFunc) base_info_ref,
+ (GBoxedFreeFunc) base_info_unref);
+
+ return our_type;
+}
+
static void
free_interface_list (GSList **interfaces_p)
{
@@ -78,6 +166,20 @@ free_interface_list (GSList **interfaces_p)
}
static void
+free_node_list (GSList **nodes_p)
+{
+ GSList *tmp;
+ tmp = *nodes_p;
+ while (tmp != NULL)
+ {
+ node_info_unref (tmp->data);
+ tmp = tmp->next;
+ }
+ g_slist_free (*nodes_p);
+ *nodes_p = NULL;
+}
+
+static void
free_method_list (GSList **methods_p)
{
GSList *tmp;
@@ -113,34 +215,35 @@ node_info_new (const char *name)
/* name can be NULL */
info = g_new0 (NodeInfo, 1);
- info->refcount = 1;
- info->name = g_strdup (name);
-
+ info->base.refcount = 1;
+ info->base.name = g_strdup (name);
+ info->base.type = INFO_TYPE_NODE;
+
return info;
}
void
node_info_ref (NodeInfo *info)
{
- info->refcount += 1;
+ info->base.refcount += 1;
}
void
node_info_unref (NodeInfo *info)
{
- info->refcount -= 1;
- if (info->refcount == 0)
+ info->base.refcount -= 1;
+ if (info->base.refcount == 0)
{
free_interface_list (&info->interfaces);
- g_free (info->name);
- g_free (info);
+ free_node_list (&info->nodes);
+ base_info_free (info);
}
}
const char*
node_info_get_name (NodeInfo *info)
{
- return info->name;
+ return info->base.name;
}
GSList*
@@ -157,6 +260,19 @@ node_info_add_interface (NodeInfo *info,
info->interfaces = g_slist_append (info->interfaces, interface);
}
+GSList*
+node_info_get_nodes (NodeInfo *info)
+{
+ return info->nodes;
+}
+
+void
+node_info_add_node (NodeInfo *info,
+ NodeInfo *node)
+{
+ node_info_ref (node);
+ info->nodes = g_slist_append (info->nodes, node);
+}
InterfaceInfo*
interface_info_new (const char *name)
@@ -164,35 +280,35 @@ interface_info_new (const char *name)
InterfaceInfo *info;
info = g_new0 (InterfaceInfo, 1);
- info->refcount = 1;
- info->name = g_strdup (name);
-
+ info->base.refcount = 1;
+ info->base.name = g_strdup (name);
+ info->base.type = INFO_TYPE_INTERFACE;
+
return info;
}
void
interface_info_ref (InterfaceInfo *info)
{
- info->refcount += 1;
+ info->base.refcount += 1;
}
void
interface_info_unref (InterfaceInfo *info)
{
- info->refcount -= 1;
- if (info->refcount == 0)
+ info->base.refcount -= 1;
+ if (info->base.refcount == 0)
{
free_method_list (&info->methods);
free_signal_list (&info->signals);
- g_free (info->name);
- g_free (info);
+ base_info_free (info);
}
}
const char*
interface_info_get_name (InterfaceInfo *info)
{
- return info->name;
+ return info->base.name;
}
GSList*
@@ -243,34 +359,34 @@ method_info_new (const char *name)
MethodInfo *info;
info = g_new0 (MethodInfo, 1);
- info->refcount = 1;
- info->name = g_strdup (name);
-
+ info->base.refcount = 1;
+ info->base.name = g_strdup (name);
+ info->base.type = INFO_TYPE_METHOD;
+
return info;
}
void
method_info_ref (MethodInfo *info)
{
- info->refcount += 1;
+ info->base.refcount += 1;
}
void
method_info_unref (MethodInfo *info)
{
- info->refcount -= 1;
- if (info->refcount == 0)
+ info->base.refcount -= 1;
+ if (info->base.refcount == 0)
{
free_arg_list (&info->args);
- g_free (info->name);
- g_free (info);
+ base_info_free (info);
}
}
const char*
method_info_get_name (MethodInfo *info)
{
- return info->name;
+ return info->base.name;
}
GSList*
@@ -293,34 +409,34 @@ signal_info_new (const char *name)
SignalInfo *info;
info = g_new0 (SignalInfo, 1);
- info->refcount = 1;
- info->name = g_strdup (name);
-
+ info->base.refcount = 1;
+ info->base.name = g_strdup (name);
+ info->base.type = INFO_TYPE_SIGNAL;
+
return info;
}
void
signal_info_ref (SignalInfo *info)
{
- info->refcount += 1;
+ info->base.refcount += 1;
}
void
signal_info_unref (SignalInfo *info)
{
- info->refcount -= 1;
- if (info->refcount == 0)
+ info->base.refcount -= 1;
+ if (info->base.refcount == 0)
{
free_arg_list (&info->args);
- g_free (info->name);
- g_free (info);
+ base_info_free (info);
}
}
const char*
signal_info_get_name (SignalInfo *info)
{
- return info->name;
+ return info->base.name;
}
GSList*
@@ -345,10 +461,11 @@ arg_info_new (const char *name,
ArgInfo *info;
info = g_new0 (ArgInfo, 1);
- info->refcount = 1;
-
+ info->base.refcount = 1;
+ info->base.type = INFO_TYPE_ARG;
+
/* name can be NULL */
- info->name = g_strdup (name);
+ info->base.name = g_strdup (name);
info->direction = direction;
info->type = type;
@@ -358,23 +475,22 @@ arg_info_new (const char *name,
void
arg_info_ref (ArgInfo *info)
{
- info->refcount += 1;
+ info->base.refcount += 1;
}
void
arg_info_unref (ArgInfo *info)
{
- info->refcount -= 1;
- if (info->refcount == 0)
+ info->base.refcount -= 1;
+ if (info->base.refcount == 0)
{
- g_free (info->name);
- g_free (info);
+ base_info_free (info);
}
}
const char*
arg_info_get_name (ArgInfo *info)
{
- return info->name;
+ return info->base.name;
}
int
diff --git a/glib/dbus-gidl.h b/glib/dbus-gidl.h
index 7a667240..f95abfbd 100644
--- a/glib/dbus-gidl.h
+++ b/glib/dbus-gidl.h
@@ -27,10 +27,11 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include <dbus/dbus.h>
-#include <glib.h>
+#include <glib-object.h>
G_BEGIN_DECLS
+typedef struct BaseInfo BaseInfo;
typedef struct NodeInfo NodeInfo;
typedef struct InterfaceInfo InterfaceInfo;
typedef struct MethodInfo MethodInfo;
@@ -43,13 +44,36 @@ typedef enum
ARG_OUT
} ArgDirection;
+typedef enum
+{
+ INFO_TYPE_NODE,
+ INFO_TYPE_INTERFACE,
+ INFO_TYPE_METHOD,
+ INFO_TYPE_SIGNAL,
+ INFO_TYPE_ARG
+
+} InfoType;
+
+void base_info_ref (BaseInfo *info);
+void base_info_unref (BaseInfo *info);
+InfoType base_info_get_type (BaseInfo *info);
+const char* base_info_get_name (BaseInfo *info);
+void base_info_set_name (BaseInfo *info,
+ const char *name);
+GType base_info_get_gtype (void);
+#define BASE_INFO_TYPE (base_info_get_gtype ())
+
+
NodeInfo* node_info_new (const char *name);
void node_info_ref (NodeInfo *info);
void node_info_unref (NodeInfo *info);
const char* node_info_get_name (NodeInfo *info);
GSList* node_info_get_interfaces (NodeInfo *info);
+GSList* node_info_get_nodes (NodeInfo *info);
void node_info_add_interface (NodeInfo *info,
InterfaceInfo *interface);
+void node_info_add_node (NodeInfo *info,
+ NodeInfo *child);
InterfaceInfo* interface_info_new (const char *name);
void interface_info_ref (InterfaceInfo *info);
diff --git a/glib/dbus-glib.h b/glib/dbus-glib.h
index 4015dd99..63d34485 100644
--- a/glib/dbus-glib.h
+++ b/glib/dbus-glib.h
@@ -2,6 +2,7 @@
/* dbus-glib.h GLib integration
*
* Copyright (C) 2002, 2003 CodeFactory AB
+ * Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
@@ -30,7 +31,22 @@ G_BEGIN_DECLS
#define DBUS_INSIDE_DBUS_GLIB_H 1
-void dbus_gthread_init (void);
+GQuark dbus_g_error_quark (void);
+#define DBUS_GERROR dbus_g_error_quark ()
+
+typedef enum
+{
+ /* FIXME map all the DBUS_ERROR to DBUS_GERROR, should
+ * probably be automated in some way, perhaps
+ * via lame perl script
+ */
+ DBUS_GERROR_FAILED
+} DBusGError;
+
+void dbus_set_g_error (GError **gerror,
+ DBusError *derror);
+
+void dbus_g_thread_init (void);
void dbus_connection_setup_with_g_main (DBusConnection *connection,
GMainContext *context);
void dbus_server_setup_with_g_main (DBusServer *server,
@@ -63,14 +79,57 @@ struct DBusGObjectInfo
void *dbus_internal_padding2; /**< Reserved for expansion */
};
-void dbus_gobject_class_install_info (GObjectClass *object_class,
- const DBusGObjectInfo *info);
-void dbus_connection_register_gobject (DBusConnection *connection,
- const char *at_path,
- GObject *object);
+void dbus_g_object_class_install_info (GObjectClass *object_class,
+ const DBusGObjectInfo *info);
+void dbus_connection_register_g_object (DBusConnection *connection,
+ const char *at_path,
+ GObject *object);
+
+
+typedef struct DBusGProxy DBusGProxy;
+
+DBusGProxy* dbus_gproxy_new_for_service (DBusConnection *connection,
+ const char *service_name,
+ const char *interface_name);
+DBusGProxy* dbus_gproxy_new_for_service_owner (DBusConnection *connection,
+ const char *service_name,
+ const char *interface_name,
+ GError **error);
+DBusGProxy* dbus_gproxy_new_for_object_path (DBusConnection *connection,
+ const char *path,
+ const char *interface_name);
+DBusGProxy* dbus_gproxy_new_for_interface (DBusConnection *connection,
+ const char *interface_name);
+void dbus_gproxy_ref (DBusGProxy *proxy);
+void dbus_gproxy_unref (DBusGProxy *proxy);
+gboolean dbus_gproxy_connect_signal (DBusGProxy *proxy,
+ const char *signal_name,
+ GCallback callback,
+ void *data,
+ GFreeFunc free_data_func,
+ GError **error);
+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,
+ ...);
+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);
#undef DBUS_INSIDE_DBUS_GLIB_H
G_END_DECLS
#endif /* DBUS_GLIB_H */
+
+
+
diff --git a/glib/dbus-gloader-expat.c b/glib/dbus-gloader-expat.c
index 149e7117..01587d21 100644
--- a/glib/dbus-gloader-expat.c
+++ b/glib/dbus-gloader-expat.c
@@ -163,31 +163,32 @@ expat_CharacterDataHandler (void *userData,
s, len);
}
-Parser*
+NodeInfo*
description_load_from_file (const char *filename,
GError **error)
{
char *contents;
gsize len;
- Parser *parser;
+ NodeInfo *nodes;
contents = NULL;
if (!g_file_get_contents (filename, &contents, &len, error))
return NULL;
- parser = description_load_from_string (contents, len, error);
+ nodes = description_load_from_string (contents, len, error);
g_free (contents);
- return parser;
+ return nodes;
}
-Parser*
+NodeInfo*
description_load_from_string (const char *str,
int len,
GError **error)
{
XML_Parser expat;
ExpatParseContext context;
+ NodeInfo *nodes;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
@@ -242,8 +243,11 @@ description_load_from_string (const char *str,
XML_ParserFree (expat);
g_string_free (context.content, TRUE);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- return context.parser;
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ nodes = parser_get_nodes (context.parser);
+ node_info_ref (nodes);
+ parser_unref (context.parser);
+ return nodes;
failed:
g_return_val_if_fail (error == NULL || *error != NULL, NULL);
@@ -255,3 +259,4 @@ description_load_from_string (const char *str,
parser_unref (context.parser);
return NULL;
}
+
diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c
index c33f47e8..2e5604dc 100644
--- a/glib/dbus-gmain.c
+++ b/glib/dbus-gmain.c
@@ -25,6 +25,10 @@
#include "dbus-glib.h"
#include "dbus-gtest.h"
+#include <libintl.h>
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+
/**
* @defgroup DBusGLib GLib bindings
* @ingroup DBus
@@ -494,6 +498,43 @@ dbus_server_setup_with_g_main (DBusServer *server,
g_error ("Not enough memory to set up DBusServer for use with GLib");
}
+/**
+ * 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);
+}
+
/** @} */ /* end of public API */
#ifdef DBUS_BUILD_TESTS
diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c
index b0f6c139..6e65770f 100644
--- a/glib/dbus-gobject.c
+++ b/glib/dbus-gobject.c
@@ -24,6 +24,7 @@
#include <config.h>
#include "dbus-glib.h"
#include "dbus-gtest.h"
+#include "dbus-gutils.h"
#include <string.h>
/**
@@ -102,6 +103,7 @@ gobject_unregister_function (DBusConnection *connection,
object = G_OBJECT (user_data);
+ /* FIXME */
}
@@ -187,6 +189,15 @@ handle_introspect (DBusConnection *connection,
unsigned int i;
GType last_type;
DBusMessage *ret;
+ char **path;
+ char **children;
+
+ if (!dbus_message_get_path_decomposed (message, &path))
+ g_error ("Out of memory");
+
+ if (!dbus_connection_list_registered (connection, (const char**) path,
+ &children))
+ g_error ("Out of memory");
xml = g_string_new (NULL);
@@ -268,13 +279,23 @@ handle_introspect (DBusConnection *connection,
g_free (specs);
+ /* Append child nodes */
+
+ i = 0;
+ while (children[i])
+ {
+ g_string_append_printf (xml, " <node name=\"%s\"/>\n",
+ children[i]);
+ ++i;
+ }
+
/* Close the XML, and send it to the requesting app */
g_string_append (xml, "</node>\n");
ret = dbus_message_new_method_return (message);
if (ret == NULL)
- g_error ("out of memory");
+ g_error ("Out of memory");
dbus_message_append_args (message,
DBUS_TYPE_STRING, xml->str,
@@ -285,6 +306,9 @@ handle_introspect (DBusConnection *connection,
g_string_free (xml, TRUE);
+ dbus_free_string_array (path);
+ dbus_free_string_array (children);
+
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -642,15 +666,15 @@ static DBusObjectPathVTable gobject_dbus_vtable = {
* class_init() for the object class.
*
* Once introspection information has been installed, instances of the
- * object registered with dbus_connection_register_gobject() can have
+ * object registered with dbus_connection_register_g_object() can have
* their methods invoked remotely.
*
* @param object_class class struct of the object
* @param info introspection data generated by dbus-glib-tool
*/
void
-dbus_gobject_class_install_info (GObjectClass *object_class,
- const DBusGObjectInfo *info)
+dbus_g_object_class_install_info (GObjectClass *object_class,
+ const DBusGObjectInfo *info)
{
g_return_if_fail (G_IS_OBJECT_CLASS (object_class));
@@ -666,55 +690,6 @@ dbus_gobject_class_install_info (GObjectClass *object_class,
g_static_mutex_unlock (&info_hash_mutex);
}
-static char**
-split_path (const char *path)
-{
- int len;
- char **split;
- int n_components;
- int i, j, comp;
-
- len = strlen (path);
-
- n_components = 0;
- i = 0;
- while (i < len)
- {
- if (path[i] == '/')
- n_components += 1;
- ++i;
- }
-
- split = g_new0 (char*, n_components + 1);
-
- comp = 0;
- i = 0;
- while (i < len)
- {
- if (path[i] == '/')
- ++i;
- j = i;
-
- while (j < len && path[j] != '/')
- ++j;
-
- /* Now [i, j) is the path component */
- g_assert (i < j);
- g_assert (path[i] != '/');
- g_assert (j == len || path[j] == '/');
-
- split[comp] = g_strndup (&path[i], j - i + 1);
-
- split[comp][j-i] = '\0';
-
- ++comp;
- i = j;
- }
- g_assert (i == len);
-
- return split;
-}
-
/**
* Registers a GObject at the given path. Properties, methods, and signals
* of the object can then be accessed remotely. Methods are only available
@@ -729,9 +704,9 @@ split_path (const char *path)
* @param object the object
*/
void
-dbus_connection_register_gobject (DBusConnection *connection,
- const char *at_path,
- GObject *object)
+dbus_connection_register_g_object (DBusConnection *connection,
+ const char *at_path,
+ GObject *object)
{
char **split;
@@ -739,7 +714,7 @@ dbus_connection_register_gobject (DBusConnection *connection,
g_return_if_fail (at_path != NULL);
g_return_if_fail (G_IS_OBJECT (object));
- split = split_path (at_path);
+ split = _dbus_gutils_split_path (at_path);
if (!dbus_connection_register_object_path (connection,
(const char**) split,
diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c
index f7264b5e..16d17f3d 100644
--- a/glib/dbus-gparser.c
+++ b/glib/dbus-gparser.c
@@ -262,7 +262,15 @@ parse_node (Parser *parser,
return FALSE;
}
+
node = node_info_new (name);
+
+ if (parser->node_stack != NULL)
+ {
+ node_info_add_node (parser->node_stack->data,
+ node);
+ }
+
parser->node_stack = g_slist_prepend (parser->node_stack,
node);
diff --git a/glib/dbus-gparser.h b/glib/dbus-gparser.h
index 3e87165b..cc58e5e0 100644
--- a/glib/dbus-gparser.h
+++ b/glib/dbus-gparser.h
@@ -52,11 +52,11 @@ gboolean parser_content (Parser *parser,
gboolean parser_finished (Parser *parser,
GError **error);
-Parser* description_load_from_file (const char *filename,
- GError **error);
-Parser* description_load_from_string (const char *str,
- int len,
- GError **error);
+NodeInfo* description_load_from_file (const char *filename,
+ GError **error);
+NodeInfo* description_load_from_string (const char *str,
+ int len,
+ GError **error);
NodeInfo* parser_get_nodes (Parser *parser);
diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c
index 8951707b..59d86a31 100644
--- a/glib/dbus-gproxy.c
+++ b/glib/dbus-gproxy.c
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#include "dbus-gproxy.h"
+#include "dbus-glib.h"
/**
* @addtogroup DBusGLibInternals
@@ -165,23 +165,59 @@ dbus_gproxy_unref (DBusGProxy *proxy)
* To collect the results of the call (which may be an error,
* or a reply), use dbus_gproxy_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 first_arg_type type of the first argument
*
* @returns opaque pending call object
- *
- */
+ * */
DBusPendingCall*
dbus_gproxy_begin_call (DBusGProxy *proxy,
const char *method,
int first_arg_type,
...)
{
+ DBusPendingCall *pending;
+ DBusMessage *message;
+ va_list args;
+
g_return_val_if_fail (proxy != NULL, NULL);
LOCK_PROXY (proxy);
+ message = dbus_message_new_method_call (proxy->service,
+ proxy->interface,
+ proxy->path,
+ method);
+ if (message == NULL)
+ goto oom;
+
+ 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_with_reply (proxy->connection,
+ message,
+ &pending,
+ -1))
+ goto oom;
+
UNLOCK_PROXY (proxy);
+
+ return pending;
+
+ oom:
+ /* FIXME we should create a pending call that's
+ * immediately completed with an error status without
+ * ever going on the wire.
+ */
+
+ g_error ("Out of memory");
+ return NULL;
}
/**
@@ -189,7 +225,9 @@ dbus_gproxy_begin_call (DBusGProxy *proxy,
* initiated with dbus_gproxy_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.
+ * 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.
*
* If the call results in an error, the error is set as normal for
* GError and the function returns #FALSE.
@@ -198,12 +236,15 @@ dbus_gproxy_begin_call (DBusGProxy *proxy,
* method are stored in the provided varargs list.
* The list should be terminated with DBUS_TYPE_INVALID.
*
+ * This function doesn't affect the reference count of the
+ * #DBusPendingCall, the caller of dbus_gproxy_begin_call() still owns
+ * a reference.
+ *
* @param proxy a proxy for a remote interface
* @param pending the pending call from dbus_gproxy_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
- */
+ * @returns #FALSE if an error is set */
gboolean
dbus_gproxy_end_call (DBusGProxy *proxy,
DBusPendingCall *pending,
@@ -211,10 +252,37 @@ dbus_gproxy_end_call (DBusGProxy *proxy,
int first_arg_type,
...)
{
+ DBusMessage *message;
+ va_list args;
+ DBusError derror;
+
g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (pending != NULL, FALSE);
+
LOCK_PROXY (proxy);
+ dbus_pending_call_block (pending);
+ message = dbus_pending_call_get_reply (pending);
+
+ g_assert (message != NULL);
+
+ dbus_error_init (&derror);
+ va_start (args, first_arg_type);
+ if (!dbus_message_get_args_valist (message, &derror, first_arg_type, args))
+ {
+ va_end (args);
+ goto error;
+ }
+ va_end (args);
+
UNLOCK_PROXY (proxy);
+
+ return TRUE;
+
+ error:
+ dbus_set_g_error (error, &derror);
+ dbus_error_free (&derror);
+ return FALSE;
}
/**
@@ -224,18 +292,17 @@ dbus_gproxy_end_call (DBusGProxy *proxy,
* dbus_connection_flush().
*
* The message is modified to be addressed to the target interface.
- * That is, a destination service field or whatever is needed
- * will be added to the message.
+ * That is, a destination service field or whatever is needed will be
+ * added to the message. The basic point of this function is to add
+ * the necessary header fields, otherwise it's equivalent to
+ * dbus_connection_send().
*
* This function adds a reference to the message, so the caller
* still owns its original reference.
- *
- * @todo fix for sending to interfaces and object IDs
*
* @param proxy a proxy for a remote interface
* @param message the message to address and send
- * @param client_serial return location for message's serial, or #NULL
- */
+ * @param client_serial return location for message's serial, or #NULL */
void
dbus_gproxy_send (DBusGProxy *proxy,
DBusMessage *message,
@@ -247,17 +314,19 @@ dbus_gproxy_send (DBusGProxy *proxy,
if (proxy->service)
{
if (!dbus_message_set_destination (message, proxy->service))
- g_error ("Out of memory\n");
+ g_error ("Out of memory");
}
if (proxy->interface)
{
- /* FIXME */
+ if (!dbus_message_set_interface (message, proxy->interface))
+ g_error ("Out of memory");
}
if (proxy->path)
{
- /* FIXME */
+ if (!dbus_message_set_path (message, proxy->path))
+ g_error ("Out of memory");
}
-
+
if (!dbus_connection_send (proxy->connection, message, client_serial))
g_error ("Out of memory\n");
diff --git a/glib/dbus-gtest.c b/glib/dbus-gtest.c
index b853d3ed..48cd13f0 100644
--- a/glib/dbus-gtest.c
+++ b/glib/dbus-gtest.c
@@ -56,6 +56,10 @@ dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir)
else
printf ("No test data!\n");
+ printf ("%s: running utils tests\n", "dbus-glib-test");
+ if (!_dbus_gutils_test (test_data_dir))
+ die ("gutils");
+
printf ("%s: running mainloop integration tests\n", "dbus-glib-test");
if (!_dbus_gmain_test (test_data_dir))
die ("gmain");
diff --git a/glib/dbus-gtest.h b/glib/dbus-gtest.h
index 6a33bdae..1174eb0a 100644
--- a/glib/dbus-gtest.h
+++ b/glib/dbus-gtest.h
@@ -28,6 +28,7 @@
dbus_bool_t _dbus_gmain_test (const char *test_data_dir);
dbus_bool_t _dbus_gobject_test (const char *test_data_dir);
+dbus_bool_t _dbus_gutils_test (const char *test_data_dir);
void dbus_glib_internal_do_not_use_run_tests (const char *test_data_dir);
diff --git a/glib/dbus-gthread.c b/glib/dbus-gthread.c
index 71a3c1f5..eb3e5572 100644
--- a/glib/dbus-gthread.c
+++ b/glib/dbus-gthread.c
@@ -165,7 +165,7 @@ dbus_gcondvar_wake_all (DBusCondVar *cond)
* other function in the D-BUS API.
*/
void
-dbus_gthread_init (void)
+dbus_g_thread_init (void)
{
if (!g_thread_supported ())
g_error ("g_thread_init() must be called before dbus_threads_init()");
diff --git a/test/Makefile.am b/test/Makefile.am
index ab04496e..84089517 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -89,7 +89,7 @@ all-local:
for D in $(TESTDIRS); do \
test -d $(top_builddir)/test/$$D || mkdir $(top_builddir)/test/$$D || exit 1 ; \
done ; \
- if test $(srcdir) != . ; then \
+ if ! (test $(srcdir) = . || test $(srcdir) -ef .) ; then \
FILES=`(cd $(srcdir) && $(FIND_TESTS))` ; \
for F in $$FILES; do \
SRC=$(srcdir)/$$F ; \
diff --git a/test/glib/test-profile.c b/test/glib/test-profile.c
index 6d9d8e7f..23547a1f 100644
--- a/test/glib/test-profile.c
+++ b/test/glib/test-profile.c
@@ -185,7 +185,7 @@ main (int argc, char *argv[])
int i;
g_thread_init (NULL);
- dbus_gthread_init ();
+ dbus_g_thread_init ();
dbus_error_init (&error);
server = dbus_server_listen ("unix:tmpdir="DBUS_TEST_SOCKET_DIR,
diff --git a/test/glib/test-thread-client.c b/test/glib/test-thread-client.c
index d51d4e6a..122c839a 100644
--- a/test/glib/test-thread-client.c
+++ b/test/glib/test-thread-client.c
@@ -66,7 +66,7 @@ main (int argc, char *argv[])
int i;
g_thread_init (NULL);
- dbus_gthread_init ();
+ dbus_g_thread_init ();
if(argc < 2)
{
diff --git a/test/glib/test-thread-server.c b/test/glib/test-thread-server.c
index 8898ca7f..dd560328 100644
--- a/test/glib/test-thread-server.c
+++ b/test/glib/test-thread-server.c
@@ -178,7 +178,7 @@ main (int argc, char *argv[])
DBusError error;
g_thread_init (NULL);
- dbus_gthread_init ();
+ dbus_g_thread_init ();
if (argc < 2)
{
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 80957854..a6a38a97 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_X_CFLAGS)
+INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_X_CFLAGS) $(DBUS_GTK_CFLAGS) -DDBUS_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\"
if HAVE_GLIB
GLIB_TOOLS=dbus-monitor
@@ -6,7 +6,13 @@ else
GLIB_TOOLS=
endif
-bin_PROGRAMS=dbus-send $(GLIB_TOOLS) dbus-launch dbus-cleanup-sockets
+if HAVE_GTK
+GTK_TOOLS=dbus-viewer
+else
+GTK_TOOLS=
+endif
+
+bin_PROGRAMS=dbus-send $(GLIB_TOOLS) dbus-launch dbus-cleanup-sockets $(GTK_TOOLS)
dbus_send_SOURCES= \
dbus-print-message.c \
@@ -24,9 +30,17 @@ dbus_launch_SOURCES= \
dbus_cleanup_sockets_SOURCES= \
dbus-cleanup-sockets.c
+dbus_viewer_SOURCES= \
+ dbus-tree-view.c \
+ dbus-tree-view.h \
+ dbus-viewer.c
+
dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la
dbus_monitor_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
dbus_launch_LDADD= $(DBUS_X_LIBS)
+dbus_viewer_LDADD= $(top_builddir)/glib/libdbus-gtool.la $(DBUS_GTK_LIBS)
man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1
EXTRA_DIST = $(man_MANS)
+
+