# HG changeset patch # User Richard Laager # Date 1179561519 0 # Node ID 9a66d81627e986a0f2bcfeda76efcfd77f8aa44c # Parent b26a225b6fc68da9228e92da84c1f3984033bac1# Parent 7484b56a82f0daf86ca5ae07e8de8ef68dca6434 propagate from branch 'im.pidgin.pidgin' (head 06b088941860bc00cfc69da2f4e9a9282685268b) to branch 'org.maemo.garage.pidgin.pidgin.dbus_uniq' (head 98753fbfda68c831c90892bc2e5fa903a357e92d) diff -r b26a225b6fc6 -r 9a66d81627e9 libpurple/core.c --- a/libpurple/core.c Sat May 19 07:58:34 2007 +0000 +++ b/libpurple/core.c Sat May 19 07:58:39 2007 +0000 @@ -48,7 +48,11 @@ #include "util.h" #ifdef HAVE_DBUS +# define DBUS_API_SUBJECT_TO_CHANGE +# include +# include "dbus-purple.h" # include "dbus-server.h" +# include "dbus-bindings.h" #endif struct PurpleCore @@ -276,6 +280,86 @@ return _ops; } +#ifdef HAVE_DBUS +static char *purple_dbus_owner_user_dir(void) +{ + DBusMessage *msg = NULL, *reply = NULL; + DBusConnection *dbus_connection = NULL; + DBusError dbus_error; + char *remote_user_dir = NULL; + + if ((dbus_connection = purple_dbus_get_connection()) == NULL) + return NULL; + + if ((msg = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, "PurpleUserDir")) == NULL) + return NULL; + + dbus_error_init(&dbus_error); + reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error); + dbus_message_unref(msg); + dbus_error_free(&dbus_error); + + if (reply) { + dbus_error_init(&dbus_error); + dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_STRING, &remote_user_dir, DBUS_TYPE_INVALID); + remote_user_dir = g_strdup(remote_user_dir); + dbus_error_free(&dbus_error); + dbus_message_unref(reply); + } + + return remote_user_dir; +} + +static void purple_dbus_owner_show_buddy_list(void) +{ + DBusError dbus_error; + DBusMessage *msg = NULL, *reply = NULL; + DBusConnection *dbus_connection = NULL; + + if ((dbus_connection = purple_dbus_get_connection()) == NULL) + return; + + if ((msg = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, "PurpleBlistShow")) == NULL) + return; + + dbus_error_init(&dbus_error); + if ((reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error)) != NULL) { + dbus_message_unref(msg); + } + dbus_error_free(&dbus_error); +} +#endif /* HAVE_DBUS */ + +gboolean purple_core_ensure_single_instance() +{ +gboolean is_single_instance = TRUE; +#ifdef HAVE_DBUS + /* in the future, other mechanisms might have already set this to FALSE */ + if (is_single_instance) { + if (!purple_dbus_is_owner()) { + const char *user_dir = purple_user_dir(); + char *dbus_owner_user_dir = purple_dbus_owner_user_dir(); + + if (NULL == user_dir && NULL != dbus_owner_user_dir) + is_single_instance = TRUE; + else if (NULL != user_dir && NULL == dbus_owner_user_dir) + is_single_instance = TRUE; + else if (NULL == user_dir && NULL == dbus_owner_user_dir) + is_single_instance = FALSE; + else + is_single_instance = strcmp(dbus_owner_user_dir, user_dir); + + if (!is_single_instance) + purple_dbus_owner_show_buddy_list(); + + g_free(dbus_owner_user_dir); + } + } +#endif /* HAVE_DBUS */ + + return is_single_instance; +} + static gboolean move_and_symlink_dir(const char *path, const char *basename, const char *old_base, const char *new_base, const char *relative) { diff -r b26a225b6fc6 -r 9a66d81627e9 libpurple/core.h --- a/libpurple/core.h Sat May 19 07:58:34 2007 +0000 +++ b/libpurple/core.h Sat May 19 07:58:39 2007 +0000 @@ -121,6 +121,14 @@ */ gboolean purple_core_migrate(void); +/** + * Ensures that only one instance is running. + * + * @return A boolean such that @c TRUE indicates that this is the first instance, + * whereas @c FALSE indicates that there is another instance running. + */ +gboolean purple_core_ensure_single_instance(void); + #ifdef __cplusplus } #endif diff -r b26a225b6fc6 -r 9a66d81627e9 libpurple/dbus-server.c --- a/libpurple/dbus-server.c Sat May 19 07:58:34 2007 +0000 +++ b/libpurple/dbus-server.c Sat May 19 07:58:39 2007 +0000 @@ -65,6 +65,12 @@ static GHashTable *map_id_type; static gchar *init_error; +static int dbus_request_name_reply = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; + +gboolean purple_dbus_is_owner(void) +{ + return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER == dbus_request_name_reply); +} /** * This function initializes the pointer-id traslation system. It @@ -592,6 +598,7 @@ return; } + dbus_request_name_reply = result = dbus_bus_request_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, 0, &error); diff -r b26a225b6fc6 -r 9a66d81627e9 libpurple/dbus-server.h --- a/libpurple/dbus-server.h Sat May 19 07:58:34 2007 +0000 +++ b/libpurple/dbus-server.h Sat May 19 07:58:39 2007 +0000 @@ -169,6 +169,11 @@ void *purple_dbus_get_handle(void); /** + * Determines whether this instance owns the DBus service name + */ +gboolean purple_dbus_is_owner(); + +/** * Starts Purple's D-BUS server. It is responsible for handling DBUS * requests from other applications. */ diff -r b26a225b6fc6 -r 9a66d81627e9 pidgin/gtkmain.c --- a/pidgin/gtkmain.c Sat May 19 07:58:34 2007 +0000 +++ b/pidgin/gtkmain.c Sat May 19 07:58:39 2007 +0000 @@ -730,6 +730,15 @@ abort(); } + if (!purple_core_ensure_single_instance()) { + purple_core_quit(); +#ifdef HAVE_SIGNAL_H + g_free(segfault_message); +#endif + return 0; + } + + /* TODO: Move blist loading into purple_blist_init() */ purple_set_blist(purple_blist_new()); purple_blist_load();