/srv/mercurial-server/detachablepurple: be7eafffa0b9: Introduced...
Gilles Bedel
gillux at cpw.pidgin.im
Fri Jun 15 22:01:29 EDT 2012
Changeset: be7eafffa0b91f943ac2b023c688cbef8c8acc99
Author: Gilles Bedel <gillux at cpw.pidgin.im>
Date: 2011-05-19 19:45 +0000
Branch: cpw.gillux.detachablepurple
URL: http://hg.pidgin.im/srv/mercurial-server/detachablepurple/rev/be7eafffa0b9
Description:
Introduced the switch from dbus-glib to gdbus, with:
- the code needed to acquire the bus
- a "virtual function", (*dbus_register), aimed to be set by
all the PurpleObjects to register themselves on DBus.
diffstat:
configure.ac | 2 +-
libpurple/dbus-bindings.h | 2 +-
libpurple/dbus-server.c | 115 ++++++++++++++++++++++++++++++----------------
libpurple/dbus-server.h | 9 +++
libpurple/dbus/account.c | 2 +-
libpurple/pobject.c | 6 +-
libpurple/pobject.h | 18 ++++++-
7 files changed, 107 insertions(+), 47 deletions(-)
diffs (truncated from 316 to 300 lines):
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -328,7 +328,7 @@
dnl #######################################################################
dnl # Check for GLib 2.16 (required)
dnl #######################################################################
-PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16.0 gobject-2.0 gmodule-2.0 gthread-2.0 gio-2.0], , [
AC_MSG_RESULT(no)
AC_MSG_ERROR([
diff --git a/libpurple/dbus-bindings.h b/libpurple/dbus-bindings.h
--- a/libpurple/dbus-bindings.h
+++ b/libpurple/dbus-bindings.h
@@ -107,7 +107,7 @@
DBusConnection *purple_dbus_get_connection(void);
-DBusGConnection *purple_dbus_get_g_connection(void);
+GDBusConnection *purple_gdbus_get_connection(void);
#ifdef __cplusplus
}
diff --git a/libpurple/dbus-server.c b/libpurple/dbus-server.c
--- a/libpurple/dbus-server.c
+++ b/libpurple/dbus-server.c
@@ -35,6 +35,7 @@
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus-glib-bindings.h>
+#include <gio/gio.h>
#include "account.h"
#include "accountlist.h"
@@ -87,6 +88,14 @@
static GHashTable *map_id_node;
static GHashTable *map_id_type;
+/* The bus acquiring process is asynchronous. We first ask to get it,
+ * then the other parts of purple are initialized, and then when we
+ * reach the program main loop, the on_bus_acquired callback is called.
+ * Therefore we need something to remember the objects created during
+ * the initialization that we will need to register on DBus when we get
+ * the bus. We temporary hold a reference to such objects in this list. */
+static GSList *dbus_obj_to_register = NULL;
+
static gchar *init_error;
static int dbus_request_name_reply = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
@@ -524,14 +533,14 @@
/* DBus bindings ... */
/**************************************************************/
-static DBusGConnection *purple_dbus_g_connection;
+static GDBusConnection *purple_gdbus_connection;
static DBusConnection *purple_dbus_connection;
-DBusGConnection *
-purple_dbus_get_g_connection(void)
+GDBusConnection *
+purple_gdbus_get_connection(void)
{
- return purple_dbus_g_connection;
+ return purple_gdbus_connection;
}
DBusConnection *
@@ -721,8 +730,8 @@
GError *gerror = NULL;
dbus_error_init(&error);
- purple_dbus_g_connection = dbus_g_bus_get(DBUS_BUS_STARTER, &gerror);
- purple_dbus_connection = dbus_g_connection_get_connection(purple_dbus_g_connection);
+ //purple_gdbus_connection = g_bus_get_sync(G_BUS_TYPE_STARTER, NULL, &gerror);
+ purple_dbus_connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
if (purple_dbus_connection == NULL)
{
@@ -772,54 +781,80 @@
PURPLE_DBUS_REGISTER_BINDINGS(purple_dbus_get_handle());
}
+void
+purple_dbus_register_object(gpointer object)
+{
+ if (purple_gdbus_connection)
+ purple_object_register_on_dbus(object, purple_gdbus_connection);
+ else
+ dbus_obj_to_register = g_slist_append(dbus_obj_to_register,
+ g_object_ref(object));
+}
+
+/* Note that this callback will not be called until we reach the event loop,
+ * after everything is initialized. Thatâs why we need to put our objects
+ * in the dbus_obj_to_register GSList, to register them later, when we have
+ * acquired the bus.
+ */
static void
-purple_dbus_g_init(void)
+on_bus_acquired(GDBusConnection *connection, const gchar *name,
+ gpointer user_data)
{
- DBusGProxy* dbus_proxy;
+ GObject *obj;
+ GSList* obj_list;
+
+ purple_gdbus_connection = connection;
+ for (obj_list = dbus_obj_to_register; obj_list; obj_list = obj_list->next) {
+ obj = G_OBJECT(obj_list->data);
+ /* If we are owning the last a reference, it means we are going
+ * to destroy it, so donât bother registering it on DBus. */
+ if (obj->ref_count > 1)
+ purple_object_register_on_dbus(obj_list->data, connection);
+ g_object_unref(obj);
+ }
+
+ g_slist_free(dbus_obj_to_register);
+}
+
+static void
+on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+ /* TODO: Handle this properly. */
+ purple_debug_error("dbus", "Name %s lost!", name);
+}
+
+static void
+purple_gdbus_init(void)
+{
+ guint owner_id;
GError *error = NULL;
- guint request_ret;
- /* In remote mode we need to register the marshallers
- * we will use to receive the signals sent by the daemon */
if (purple_core_is_remote_mode()) {
/* Initialize the "dbus path name -> gobject" hash table */
dbus_path_gobjects = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, NULL);
}
- /* In daemon mode create a proxy for the purple service, so we can
- * publish our gobjects on DBus.
+ /* In daemon mode we need to own our name on the bus,
+ * so we can publish our gobjects on DBus.
*/
if (purple_core_is_daemon_mode()) {
- dbus_proxy = dbus_g_proxy_new_for_name(purple_dbus_get_g_connection(),
- DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
- if (!dbus_proxy) {
- purple_debug_error("dbus", "Unable to create proxy\n");
- return;
- }
-
- if (!org_freedesktop_DBus_request_name(dbus_proxy,
- DBUS_PURPLE_SERVICE, 0,
- &request_ret, &error)) {
- purple_debug_error("dbus",
- "Unable to request the name of service "
- DBUS_PURPLE_SERVICE ": %s\n",
- error->message);
- g_object_unref(dbus_proxy);
- g_error_free(error);
- return;
- }
- g_object_unref(dbus_proxy);
- /* We should also care about request_ret */
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, DBUS_PURPLE_SERVICE,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ NULL, /* on_name_acquired */
+ on_name_lost, /* on_name_lost */
+ NULL, NULL);
+ /* TODO: handle fail of owning the name. */
}
/* In remote and daemon mode, we create our singleton objects */
+
+ /* Instantiate the PurpleConstructor */
+ purple_constructor_do_init();
+
/* Instantiate the PurpleDBusCallback. */
purple_dbus_callback_do_init();
-
- /* Instantiate and publish the PurpleConstructor */
- purple_constructor_do_init();
}
@@ -1007,11 +1042,11 @@
if (init_error != NULL)
purple_debug_error("dbus", "%s\n", init_error);
- purple_dbus_g_init();
+ purple_gdbus_init();
}
static void
-purple_dbus_g_uninit(void)
+purple_gdbus_uninit(void)
{
if (purple_core_is_remote_mode())
g_hash_table_destroy(dbus_path_gobjects);
@@ -1038,5 +1073,5 @@
g_free(init_error);
init_error = NULL;
- purple_dbus_g_uninit();
+ purple_gdbus_uninit();
}
diff --git a/libpurple/dbus-server.h b/libpurple/dbus-server.h
--- a/libpurple/dbus-server.h
+++ b/libpurple/dbus-server.h
@@ -179,6 +179,15 @@
gboolean purple_dbus_is_owner(void);
/**
+ * "Busless" function to register a PurpleObject on DBus.
+ * If the bus is acquired, it calls the ->dbus_register() operation.
+ * Otherwise, it will do it when the bus is acquired.
+ *
+ * @param obj The object to register. Must be a subclass of PurpleObject.
+ */
+void purple_dbus_register_object(gpointer object);
+
+/**
* Starts Purple's D-BUS server. It is responsible for handling DBUS
* requests from other applications.
*/
diff --git a/libpurple/dbus/account.c b/libpurple/dbus/account.c
--- a/libpurple/dbus/account.c
+++ b/libpurple/dbus/account.c
@@ -245,7 +245,7 @@
PurpleRunningMode mode;
/* First, remotely create a new account */
- dbus_proxy = dbus_g_proxy_new_for_name(purple_dbus_get_g_connection(),
+ dbus_proxy = dbus_g_proxy_new_for_name(purple_gdbus_get_connection(),
DBUS_PURPLE_SERVICE,
DBUS_CONSTRUCTOR_PATH,
DBUS_CONSTRUCTOR_INTERFACE);
diff --git a/libpurple/pobject.c b/libpurple/pobject.c
--- a/libpurple/pobject.c
+++ b/libpurple/pobject.c
@@ -459,14 +459,14 @@
if (purple_core_is_remote_mode() || purple_core_is_mirror_mode()) {
/* One for the org.freedesktop.DBus.Properties interface */
dbus_proxy = dbus_g_proxy_new_for_name(
- purple_dbus_get_g_connection(),
+ purple_gdbus_get_connection(),
DBUS_PURPLE_SERVICE, dbus_path,
DBUS_INTERFACE_PROPERTIES);
priv->dbus_props_proxy = dbus_proxy;
/* One for the provided interface */
dbus_proxy = dbus_g_proxy_new_for_name(
- purple_dbus_get_g_connection(),
+ purple_gdbus_get_connection(),
DBUS_PURPLE_SERVICE, dbus_path,
dbus_interface);
priv->dbus_obj_proxy = dbus_proxy;
@@ -487,7 +487,7 @@
else if (purple_core_is_daemon_mode()) {
/* Register our object as at dbus_path */
dbus_g_connection_register_g_object(
- purple_dbus_get_g_connection(),
+ purple_gdbus_get_connection(),
dbus_path, G_OBJECT(pobj));
/* Remember the purple interface */
diff --git a/libpurple/pobject.h b/libpurple/pobject.h
--- a/libpurple/pobject.h
+++ b/libpurple/pobject.h
@@ -26,6 +26,7 @@
#ifdef HAVE_DBUS
# include <dbus/dbus-glib-bindings.h>
+# include <gio/gio.h>
#endif
#define PURPLE_TYPE_OBJECT (purple_object_get_type())
@@ -47,8 +48,13 @@
struct _PurpleObjectClass
{
GObjectClass gparent;
-
+#ifdef HAVE_DBUS
+ /* A function that should register the object on DBus. */
+ guint (*dbus_register)(gpointer object, GDBusConnection *connection);
+ void (*_purple_reserved[3])(void);
+#else
void (*_purple_reserved[4])(void);
+#endif
};
G_BEGIN_DECLS
@@ -155,6 +161,16 @@
More information about the Commits
mailing list