soc.2010.detachablepurple: 26c217ac: A first draft of the RPC system and the ...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Fri Jun 18 07:14:53 EDT 2010


-----------------------------------------------------------------
Revision: 26c217ac06a699c51e69e806a01be2719fb8b134
Ancestor: 18a99954b390eb638a4cd8a365cb5a403f185d6d
Author: gillux at soc.pidgin.im
Date: 2010-06-18T07:50:59
Branch: im.pidgin.soc.2010.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/26c217ac06a699c51e69e806a01be2719fb8b134

Added files:
        libpurple/account-dbus.c libpurple/account-dbus.h
        libpurple/dbus-prototypes/account.xml purpled/Makefile.am
        purpled/purpled.c purpled/purpled.h purpled/purpled.pc.in
Added directories:
        libpurple/dbus-prototypes purpled
Modified files:
        Makefile.am configure.ac libpurple/Makefile.am
        libpurple/account.c libpurple/core.c libpurple/core.h
        libpurple/dbus-bindings.h libpurple/dbus-maybe.h
        libpurple/dbus-purple.h libpurple/dbus-server.c
        libpurple/example/Makefile.am

ChangeLog: 

A first draft of the RPC system and the libpurple daemon purpled.

Added a new flag in core.c to say if libpurple acts as a daemon (normal mode) or
as a proxy UI client (remote mode).
Added "purpled" (the daemon) which basically consists in a nullclient.
A new dbus service that use the dbus glib bindings (im.pidgin.purple) works
at the same time as the current dbus low-level implementation.
Currently it only provides the PurpleAccount object with its SetPassword method,
which remotely runs purple_account_set_password(). In addition the glib dbus
bindings make PurpleAccount getters and setters available (try to run
dbus-send --print-reply --session --dest="im.pidgin.purple"
"/im/pidgin/purple/account" "org.freedesktop.DBus.Introspectable.Introspect").
Added a remotenullclient which can be used in conjunction with purpled to test
this stuff. Alternatively use: dbus-send --print-reply --session
--dest="im.pidgin.purple" "/im/pidgin/purple/account" <interface>.<method> [args]

-------------- next part --------------
============================================================
--- libpurple/account-dbus.c	92e104e7119e7c4c277c14a05fa4dabf6c7dccda
+++ libpurple/account-dbus.c	92e104e7119e7c4c277c14a05fa4dabf6c7dccda
@@ -0,0 +1,16 @@
+
+#include <glib.h>
+#include "account.h"
+
+/*
+ * purple_account_set_password()'s dbus twin. This is what is actually called
+ * when someone calls the associated dbus method SetPassword.
+ */
+gboolean
+DBUS_purple_account_set_password(PurpleAccount *account, gchar* password,
+                                GError** error)
+{
+    purple_account_set_password(account, password);
+    return TRUE;
+}
+
============================================================
--- libpurple/account-dbus.h	2d831e0cb82ded61325f2592acf13c395726f9d9
+++ libpurple/account-dbus.h	2d831e0cb82ded61325f2592acf13c395726f9d9
@@ -0,0 +1,3 @@
+
+gboolean DBUS_purple_account_set_password(PurpleAccount *account, gchar* password, GError** error);
+
============================================================
--- libpurple/dbus-prototypes/account.xml	c3aa9f2daab780413a455f96ab79f3871a60bb30
+++ libpurple/dbus-prototypes/account.xml	c3aa9f2daab780413a455f96ab79f3871a60bb30
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/im/pidgin/purple/account">
+	<interface name="im.pidgin.purple.account">
+		<method name="SetPassword">
+			<arg type="s" name="password" direction="in" />
+		</method>
+	</interface>
+</node>
============================================================
--- purpled/Makefile.am	81efcb3c2db532d384606abcb13eb56ed6e68610
+++ purpled/Makefile.am	81efcb3c2db532d384606abcb13eb56ed6e68610
@@ -0,0 +1,35 @@
+EXTRA_DIST = 
+
+if ENABLE_DBUS
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = purpled.pc
+
+SUBDIRS = 
+
+bin_PROGRAMS = purpled
+
+purpled_SOURCES = \
+	purpled.c
+
+purpled_headers = \
+	purpled.h
+
+purpled_LDFLAGS = 
+purpled_LDADD = \
+	$(GLIB_LIBS) \
+	$(DBUS_LIBS) \
+	$(top_builddir)/libpurple/libpurple.la
+
+AM_CPPFLAGS = \
+	-DLOCALEDIR=\"$(datadir)/locale\" \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-I$(top_builddir)/libpurple \
+	-I$(top_srcdir)/libpurple/ \
+	-I$(top_builddir) \
+	-I$(top_srcdir) \
+	$(GLIB_CFLAGS) \
+	$(DEBUG_CFLAGS) \
+	$(DBUS_CFLAGS)
+
+endif  # ENABLE_DBUS
============================================================
--- purpled/purpled.c	b588bb857cad46ef09e6f149a31d5dc7fb536a41
+++ purpled/purpled.c	b588bb857cad46ef09e6f149a31d5dc7fb536a41
@@ -0,0 +1,152 @@
+/*
+ * Purpled is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ *
+ */
+
+#include "purple.h"
+
+#include "purpled.h"
+#include "account.h" /* purple_account_new() */
+
+/* Copied verbatim from nullclient */
+#define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+typedef struct _PurpleGLibIOClosure {
+	PurpleInputFunction function;
+	guint result;
+	gpointer data;
+} PurpleGLibIOClosure;
+
+static void purple_glib_io_destroy(gpointer data)
+{
+	g_free(data);
+}
+
+static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	PurpleGLibIOClosure *closure = data;
+	PurpleInputCondition purple_cond = 0;
+
+	if (condition & PURPLE_GLIB_READ_COND)
+		purple_cond |= PURPLE_INPUT_READ;
+	if (condition & PURPLE_GLIB_WRITE_COND)
+		purple_cond |= PURPLE_INPUT_WRITE;
+
+	closure->function(closure->data, g_io_channel_unix_get_fd(source),
+			  purple_cond);
+
+	return TRUE;
+}
+
+static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function,
+							   gpointer data)
+{
+	PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
+	GIOChannel *channel;
+	GIOCondition cond = 0;
+
+	closure->function = function;
+	closure->data = data;
+
+	if (condition & PURPLE_INPUT_READ)
+		cond |= PURPLE_GLIB_READ_COND;
+	if (condition & PURPLE_INPUT_WRITE)
+		cond |= PURPLE_GLIB_WRITE_COND;
+
+#if defined _WIN32 && !defined WINPIDGIN_USE_GLIB_IO_CHANNEL
+	channel = wpurple_g_io_channel_win32_new_socket(fd);
+#else
+	channel = g_io_channel_unix_new(fd);
+#endif
+	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
+					      purple_glib_io_invoke, closure, purple_glib_io_destroy);
+
+	g_io_channel_unref(channel);
+	return closure->result;
+}
+
+static PurpleEventLoopUiOps glib_eventloops = 
+{
+	g_timeout_add,
+	g_source_remove,
+	glib_input_add,
+	g_source_remove,
+	NULL,
+#if GLIB_CHECK_VERSION(2,14,0)
+	g_timeout_add_seconds,
+#else
+	NULL,
+#endif
+
+	/* padding */
+	NULL,
+	NULL,
+	NULL
+};
+/*** End of the eventloop functions. ***/
+
+static void
+init_libpurple(void)
+{
+	purple_eventloop_set_ui_ops(&glib_eventloops);
+
+	/*
+	 * Note: currently the following code will fail if it tries to load the
+	 * accounts from your accounts.xml, because it makes it automatically
+	 * instantiate your accounts, whereas there is only a single account
+	 * exportable via dbus, yet (the /im/pidgin/purple/account object).
+	 * So spoof the user dir.
+	 */
+	purple_util_set_user_dir("/dev/null");
+
+	if (!purple_core_init(PURPLED_ID)) {
+		fprintf(stderr, "libpurple initialization failed.");
+		exit(1);
+	}
+
+	/*
+	 * Instantiate an account so that it will be accessible in dbus at
+	 * /im/pidgin/purple/account. This will have to be initiated by the
+	 * client.
+	 */
+	purple_account_new("nothing", "prpl-jabber");
+}
+
+int
+main(int argc, char **argv)
+{
+	GMainLoop *loop = g_main_loop_new(NULL, FALSE);
+
+#ifndef _WIN32
+	/* libpurple's built-in DNS resolution forks processes to perform
+	 * blocking lookups without blocking the main process.  It does not
+	 * handle SIGCHLD itself, so if the UI does not you quickly get an army
+	 * of zombie subprocesses marching around.
+	 */
+	signal(SIGCHLD, SIG_IGN);
+#endif
+
+	init_libpurple();
+	purple_eventloop_set_ui_ops(&glib_eventloops);
+
+	g_main_loop_run(loop);
+	return 0;
+}
+
============================================================
--- purpled/purpled.h	e02f613b5f48c55fc8364b84f8a6150f85ccc4a3
+++ purpled/purpled.h	e02f613b5f48c55fc8364b84f8a6150f85ccc4a3
@@ -0,0 +1,27 @@
+/*
+ * Purpled is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ *
+ */
+
+#ifndef _PURPLED_H_
+#define _PURPLED_H_
+
+#define PURPLED_ID "purpled"
+
+#endif /* _PURPLE_H_ */
============================================================
--- purpled/purpled.pc.in	a7f1b817c3ba2ac8c9d922ef2b9f1b998317e647
+++ purpled/purpled.pc.in	a7f1b817c3ba2ac8c9d922ef2b9f1b998317e647
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+
+Name: Purpled
+Description: Purpled handles detachable sessions of libpurple based clients.
+Version: @VERSION@
+Requires: purple
+
============================================================
--- Makefile.am	042cd4f1a587ff1633aaed103f0874c7cec999c6
+++ Makefile.am	396912673117ba9ec53df0a33e81b1a4ae23e3f8
@@ -127,7 +127,7 @@ distcleancheck_listfiles = find . -type 
 # line does is tell 'distcheck' to shut up and ignore those two files.
 distcleancheck_listfiles = find . -type f -a ! -name package_revision.h
 
-SUBDIRS = . libpurple doc $(GNT_DIR) $(GTK_DIR) m4macros $(PO_DIR) share/ca-certs share/sounds
+SUBDIRS = . libpurple doc $(GNT_DIR) $(GTK_DIR) purpled m4macros $(PO_DIR) share/ca-certs share/sounds
 
 docs: Doxyfile
 if HAVE_DOXYGEN
============================================================
--- configure.ac	fdb3abd7bfa2002742e7469f2aad07d011992e58
+++ configure.ac	ff43007b947cf87f36e578c3904144b28f3b7ff8
@@ -2611,6 +2611,8 @@ AC_CONFIG_FILES([Makefile
 		   finch/libgnt/gnt.pc
 		   finch/libgnt/wms/Makefile
 		   finch/plugins/Makefile
+		   purpled/Makefile
+		   purpled/purpled.pc
 		   po/Makefile.in
 		   pidgin.spec
 		  ])
============================================================
--- libpurple/Makefile.am	c27e10aa80edb816e3109c5084420d412171b987
+++ libpurple/Makefile.am	7cc991e06c754b5b0f7a724aac310297b7ed0863
@@ -203,7 +203,9 @@ purple_mediaheaders = \
 	codec.h \
 	enum-types.h
 
-purple_builtheaders = purple.h version.h marshallers.h
+purple_builtheaders = \
+	purple.h version.h marshallers.h \
+	dbus-account-server.h dbus-account-client.h
 
 marshallers.h: marshallers.list
 	@echo "Generating marshallers.h"
@@ -219,6 +221,12 @@ if ENABLE_DBUS
 
 if ENABLE_DBUS
 
+dbus-account-server.h: dbus-prototypes/account.xml
+	dbus-binding-tool --prefix=DBUS_purple_account --mode=glib-server --output=$@ $<
+
+dbus-account-client.h: dbus-prototypes/account.xml
+	dbus-binding-tool --prefix=DBUS_purple_account --mode=glib-client --output=$@ $<
+
 CLEANFILES = \
 	dbus-bindings.c \
 	dbus-client-binding.c \
@@ -234,8 +242,10 @@ CLEANFILES = \
 
 # purple dbus server
 
-dbus_sources  = dbus-server.c dbus-useful.c
-dbus_headers  = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h
+dbus_sources  = dbus-server.c dbus-useful.c \
+	account-dbus.c
+dbus_headers  = dbus-bindings.h dbus-purple.h dbus-server.h dbus-useful.h dbus-define-api.h dbus-types.h \
+	account-dbus.h
 
 dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h buddyicon.h \
                 connection.h conversation.h core.h ft.h log.h notify.h prefs.h roomlist.h \
============================================================
--- libpurple/account.c	b98f88b2980b08ff5ecd1191bbb014a7a2dbc33a
+++ libpurple/account.c	0e23f59ed035aa0a3499294c931c5e583510cc0f
@@ -43,6 +43,16 @@
 #include "util.h"
 #include "xmlnode.h"
 
+#ifdef HAVE_DBUS
+/* Provides DBUS_SERVICE_DBUS etc. */
+#  include <dbus/dbus-glib-bindings.h>
+/* Our dbus exported stuff description (generated) */
+/* Note: we are both client and server, depending on purple_core_get_remote_mode() */
+#  include "account-dbus.h"
+#  include "dbus-account-server.h"
+#  include "dbus-account-client.h"
+#endif
+
 struct _PurpleAccountPrivate
 {
 	char *username;             /**< The username. */
@@ -752,6 +762,12 @@ static void purple_account_class_init(Pu
 				G_TYPE_NONE, 0);
 #warning TODO: Setup more signals
 
+#ifdef HAVE_DBUS
+	/* Add dbus stuff (method introspection data) */
+	if(!purple_core_get_remote_mode())
+		dbus_g_object_type_install_info(PURPLE_TYPE_OBJECT,
+									&dbus_glib_DBUS_purple_account_object_info);
+#endif
 	g_type_class_add_private(klass, sizeof(PurpleAccountPrivate));
 }
 
@@ -793,6 +809,14 @@ purple_account_new(const char *username,
 	g_return_val_if_fail(username != NULL, NULL);
 	g_return_val_if_fail(protocol_id != NULL, NULL);
 
+#ifdef HAVE_DBUS
+	if(purple_core_get_remote_mode())
+		return (PurpleAccount *)dbus_g_proxy_new_for_name(purple_dbus_get_g_connection(),
+														DBUS_PURPLE_SERVICE,
+														DBUS_ACCOUNT_PATH, 
+														DBUS_ACCOUNT_INTERFACE);
+#endif
+
 	account = purple_accounts_find(username, protocol_id);
 
 	if (account != NULL)
@@ -809,6 +833,8 @@ purple_account_new(const char *username,
 
 	PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount);
 
+	PURPLE_DBUS_REGISTER_OBJECT(DBUS_ACCOUNT_PATH, account);
+
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 	if (prpl_info != NULL && prpl_info->status_types != NULL)
 		purple_account_set_status_types(account, prpl_info->status_types(account));
@@ -1359,7 +1385,22 @@ purple_account_set_password(PurpleAccoun
 purple_account_set_password(PurpleAccount *account, const char *password)
 {
 	PurpleAccountPrivate *priv;
+#ifdef HAVE_DBUS
+	GError *error = NULL;
 
+	if (purple_core_get_remote_mode()) {
+		if (!im_pidgin_purple_account_set_password((DBusGProxy *)account,
+												password, &error)) {
+			purple_debug_error("dbus", "Failed to remotely call purple_account_set_password(): %s\n",
+							error->message);
+			g_error_free(error);
+		}
+		else
+			purple_debug_info("dbus", "Successfully remotely called purple_account_set_password :-D\n");
+		return;
+	}
+#endif
+
 	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
 
 	priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
@@ -2946,6 +2987,11 @@ purple_accounts_init(void)
 void
 purple_accounts_init(void)
 {
+#ifdef HAVE_DBUS
+	DBusGProxy* dbus_proxy;
+	GError *error = NULL;
+	guint request_ret;
+#endif
 	void *handle = purple_accounts_get_handle();
 
 	purple_signal_register(handle, "account-connecting",
@@ -3030,6 +3076,31 @@ purple_accounts_init(void)
 	purple_signal_connect(conn_handle, "connection-error", handle,
 	                      PURPLE_CALLBACK(connection_error_cb), NULL);
 #endif
+
+#ifdef HAVE_DBUS
+	/* Export our objects only if we are in normal mode. */
+	if (!purple_core_get_remote_mode()) {
+		/*
+		 * Create a proxy for the account objects, so we can register them
+		 * on the bus.
+		 */
+		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");
+		} else {
+			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_error_free(error);
+			}
+			/* We should also care about request_ret */
+		}
+	}
+#endif
 }
 
 void
============================================================
--- libpurple/core.c	9c92c653f62d14cd94007a8e150f69ce659c3863
+++ libpurple/core.c	c8507e0a2b89ee1236cfce0063465f47c8ad48d6
@@ -72,6 +72,7 @@ static PurpleCore      *_core = NULL;
 
 static PurpleCoreUiOps *_ops  = NULL;
 static PurpleCore      *_core = NULL;
+static gboolean        _remote_mode = FALSE;
 
 STATIC_PROTO_INIT
 
@@ -316,6 +317,27 @@ purple_core_get_ui_ops(void)
 	return _ops;
 }
 
+gboolean
+purple_core_get_remote_mode(void)
+{
+#if HAVE_DBUS
+	return _remote_mode;
+#else
+	return FALSE;
+#endif
+}
+
+void
+purple_core_set_remote_mode(gboolean mode)
+{
+#if HAVE_DBUS
+	_remote_mode = mode;
+#else
+	if (mode)
+		purple_debug_warning("core", "Couldn't activate remote mode: this feature is not compiled in.\n");
+#endif
+}
+
 #ifdef HAVE_DBUS
 static char *purple_dbus_owner_user_dir(void)
 {
============================================================
--- libpurple/core.h	00ce2d639ef12115482b3f6806654a33ccc047d8
+++ libpurple/core.h	7bd4e9c6268135652c8b21bfca7367b6cf46cfab
@@ -142,6 +142,28 @@ PurpleCore *purple_get_core(void);
 PurpleCore *purple_get_core(void);
 
 /**
+ * Returns the remote mode flag of the purple core.
+ *
+ * Remote mode is used in detachable sessions scenarios. It is set
+ * by UI clients which want to attach and detach from purpled. As
+ * a default beheaviour this flag is FALSE.
+ *
+ * @return TRUE if remote mode is activated, FALSE if not.
+ */
+gboolean purple_core_get_remote_mode(void);
+
+/**
+ * Sets the remote mode flag of the purple core.
+ *
+ * Remote mode is used in detachable sessions scenarios. It is set
+ * by UI clients which want to attach and detach from purpled. As
+ * a default beheaviour this flag is FALSE.
+ *
+ * @param mode The wanted remote mode flag.
+ */
+void purple_core_set_remote_mode(gboolean mode);
+
+/**
  * Sets the UI ops for the core.
  *
  * @param ops A UI ops structure for the core.
============================================================
--- libpurple/dbus-bindings.h	55b8c581bc82b5fa70ee12d1b6e827ba16eb0b0e
+++ libpurple/dbus-bindings.h	cf9bc137c80c8a1d14cd0a38d74fc9d6ef839238
@@ -107,6 +107,8 @@ DBusConnection *purple_dbus_get_connecti
 
 DBusConnection *purple_dbus_get_connection(void);
 
+DBusGConnection *purple_dbus_get_g_connection(void);
+
 #ifdef __cplusplus
 }
 #endif
============================================================
--- libpurple/dbus-maybe.h	f210b7a2cfca56cc9fecc9a7a307ae5de47d0323
+++ libpurple/dbus-maybe.h	9f796119b84aea176bcccd82ddffa4c118f98840
@@ -14,6 +14,13 @@
 
 #include "dbus-server.h"
 
+#define PURPLE_DBUS_REGISTER_OBJECT(path, object) \
+G_STMT_START { \
+    if (!purple_core_get_remote_mode()) \
+         dbus_g_connection_register_g_object(purple_dbus_get_g_connection(), \
+                                             path, G_OBJECT(object)); \
+} G_STMT_END
+
 /* this provides a type check */
 #define PURPLE_DBUS_REGISTER_POINTER(ptr, type) { \
     type *typed_ptr = ptr; \
@@ -23,6 +30,8 @@
 
 #else  /* !HAVE_DBUS */
 
+#define PURPLE_DBUS_REGISTER_OBJECT(path, object)
+
 #define PURPLE_DBUS_REGISTER_POINTER(ptr, type) { \
     if (ptr) {} \
 }
============================================================
--- libpurple/dbus-purple.h	c4ff62d0358f860ec0c87f55cccc3c0875472bef
+++ libpurple/dbus-purple.h	832adde929eaddf164a190f4027a12fc7b4a8d6c
@@ -28,4 +28,8 @@
 #define DBUS_PATH_PURPLE         "/im/pidgin/purple/PurpleObject"
 #define DBUS_INTERFACE_PURPLE    "im.pidgin.purple.PurpleInterface"
 
+#define DBUS_PURPLE_SERVICE	"im.pidgin.purple"
+#define DBUS_ACCOUNT_PATH	"/im/pidgin/purple/account"
+#define DBUS_ACCOUNT_INTERFACE    "im.pidgin.purple.account"
+
 #endif /* _DBUS_PURPLE_H_ */
============================================================
--- libpurple/dbus-server.c	71e774dce7c36d2ff6b2aaea325e0145c1951c42
+++ libpurple/dbus-server.c	64719562c572c07f0e63850e964e40abf20e957e
@@ -415,8 +415,16 @@ error:
 /* DBus bindings ...                                          */
 /**************************************************************/
 
+static DBusGConnection *purple_dbus_g_connection;
+
 static DBusConnection *purple_dbus_connection;
 
+DBusGConnection *
+purple_dbus_get_g_connection(void)
+{
+	return purple_dbus_g_connection;
+}
+
 DBusConnection *
 purple_dbus_get_connection(void)
 {
@@ -601,14 +609,16 @@ purple_dbus_dispatch_init(void)
 {
 	static DBusObjectPathVTable vtable = {NULL, &purple_dbus_dispatch, NULL, NULL, NULL, NULL};
 	DBusError error;
+	GError *gerror = NULL;
 
 	dbus_error_init(&error);
-	purple_dbus_connection = dbus_bus_get(DBUS_BUS_STARTER, &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);
 
 	if (purple_dbus_connection == NULL)
 	{
 		init_error = g_strdup_printf(N_("Failed to get connection: %s"), error.message);
-		dbus_error_free(&error);
+		g_error_free(gerror);
 		return;
 	}
 
============================================================
--- libpurple/example/Makefile.am	904f30518e485f956e8bd0070618ecd62241b530
+++ libpurple/example/Makefile.am	627f86529dc474877557a279a24557d2eaa9bf3e
@@ -1,6 +1,5 @@
-noinst_PROGRAMS = nullclient
+noinst_PROGRAMS = nullclient remotenullclient
 
-nullclient_SOURCES = defines.h nullclient.c
 nullclient_DEPENDENCIES =
 nullclient_LDFLAGS = -export-dynamic
 nullclient_LDADD = \
@@ -10,6 +9,11 @@ nullclient_LDADD = \
 	$(LIBXML_LIBS) \
 	$(top_builddir)/libpurple/libpurple.la
 
+remotenullclient_SOURCES = defines.h remotenullclient.c
+remotenullclient_DEPENDENCIES = $(nullclient_DEPENDENCIES)
+remotenullclient_LDFLAGS = $(nullclient_LDFLAGS)
+remotenullclient_LDADD = $(nullclient_LDADD)
+
 AM_CPPFLAGS = \
 	-DSTANDALONE \
 	-DDATADIR=\"$(datadir)\" \


More information about the Commits mailing list