[Bluez-devel] [PATCH] [RESEND] make bluez GNOME UIs singletons

Chris Rivera
2007-12-03T15:33:05Z

[-- Attachment #1.1: Type: text/plain, Size: 130 bytes --]

I'm resending this patch since I haven't gotten a response in the original
thread in weeks. Let me know if this looks OK.

Chris

[-- Attachment #1.2: Type: text/html, Size: 153 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: bluez-gnome-singleton.patch --]
[-- Type: text/x-patch; name=bluez-gnome-singleton.patch, Size: 14037 bytes --]

Index: applet/bluetooth-applet.desktop.in
===================================================================
RCS file: /cvsroot/bluez/gnome/applet/bluetooth-applet.desktop.in,v
retrieving revision 1.1
diff -u -p -r1.1 bluetooth-applet.desktop.in
--- applet/bluetooth-applet.desktop.in 3 Apr 2007 08:09:01 -0000 1.1
+++ applet/bluetooth-applet.desktop.in 13 Nov 2007 17:04:15 -0000
@@ -3,7 +3,7 @@ Encoding=UTF-8
_Name=Bluetooth Manager
_Comment=Bluetooth Manager applet
Icon=stock_bluetooth
-Exec=bluetooth-applet
+Exec=bluetooth-applet --singleton
Terminal=false
Type=Application
Categories=
Index: applet/main.c
===================================================================
RCS file: /cvsroot/bluez/gnome/applet/main.c,v
retrieving revision 1.87
diff -u -p -r1.87 main.c
--- applet/main.c 29 Aug 2007 20:42:18 -0000 1.87
+++ applet/main.c 13 Nov 2007 17:04:16 -0000
@@ -32,9 +32,9 @@
#include <string.h>

#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>

#ifdef HAVE_HAL
-#include <dbus/dbus-glib-lowlevel.h>
#include <hal/libhal.h>
#endif

@@ -1553,7 +1553,7 @@ static void about_callback(GtkWidget *it

static void settings_callback(GObject *widget, gpointer user_data)
{
- const char *command = "bluetooth-properties";
+ const char *command = "bluetooth-properties --singleton";

if (!g_spawn_command_line_async(command, NULL))
g_printerr("Couldn't execute command: %s\n", command);
@@ -1642,7 +1642,7 @@ static void sendto_callback(GObject *wid
#if 0
static void wizard_callback(GObject *widget, gpointer user_data)
{
- const char *command = "bluetooth-wizard";
+ const char *command = "bluetooth-wizard --singleton";

if (!g_spawn_command_line_async(command, NULL))
g_printerr("Couldn't execute command: %s\n", command);
@@ -1783,11 +1783,70 @@ static void gconf_callback(GConfClient *
auto_authorize = gconf_value_get_bool(value);
}

+static DBusGConnection *register_instance (int *retval, gboolean singleton)
+{
+ DBusGConnection *sc;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ guint request_result;
+ gboolean ret;
+
+ sc = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL) {
+ g_printerr("Connecting to session bus failed: %s\n",
+ error->message);
+ g_error_free(error);
+ *retval = 1;
+ return NULL;
+ }
+
+ proxy = dbus_g_proxy_new_for_name(sc,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ ret = dbus_g_proxy_call(proxy, "RequestName", NULL,
+ G_TYPE_STRING, "org.bluez.GnomeApplet",
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &request_result,
+ G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ if (!ret) {
+ g_printerr("Failed to request name on the session bus\n");
+ dbus_g_connection_unref(sc);
+ *retval = 1;
+ return NULL;
+ }
+
+ if (request_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ *retval = 0;
+
+ if (singleton) {
+ g_print("Another instance is already running.\n");
+ dbus_g_connection_unref(sc);
+ return NULL;
+ }
+ }
+
+ return sc;
+}
+
int main(int argc, char *argv[])
{
+ GOptionContext *ctx;
GtkWidget *menu;
GError *error = NULL;
+ DBusGConnection *session_conn = NULL;
char *str;
+ int retval = 0;
+ gboolean singleton = FALSE;
+
+ GOptionEntry entries[] = {
+ { "singleton", 0, 0, G_OPTION_ARG_NONE, &singleton,
+ N_("Only allow one instance of this application"), NULL },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };

bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
@@ -1795,6 +1854,15 @@ int main(int argc, char *argv[])

gtk_init(&argc, &argv);

+ ctx = g_option_context_new("");
+ g_option_context_add_main_entries(ctx, entries, NULL);
+ if (!g_option_context_parse(ctx, &argc, &argv, &error)) {
+ g_printerr(_("parsing failed: %s\n"), error->message);
+ g_error_free(error);
+ g_option_context_free(ctx);
+ return retval;
+ }
+
#ifdef HAVE_LIBNOTIFY
notify_init("bluetooth-manager");
#endif
@@ -1806,6 +1874,10 @@ int main(int argc, char *argv[])
g_error_free(error);
exit(EXIT_FAILURE);
}
+
+ session_conn = register_instance(&retval, singleton);
+ if (!session_conn)
+ exit(retval);

gconf = gconf_client_get_default();

@@ -1863,6 +1935,9 @@ int main(int argc, char *argv[])
g_list_foreach(adapter_list, adapter_free, NULL);

dbus_g_connection_unref(conn);
+ dbus_g_connection_unref(session_conn);

+ g_option_context_free(ctx);
+
return 0;
}
Index: properties/main.c
===================================================================
RCS file: /cvsroot/bluez/gnome/properties/main.c,v
retrieving revision 1.48
diff -u -p -r1.48 main.c
--- properties/main.c 31 Jul 2007 21:37:29 -0000 1.48
+++ properties/main.c 13 Nov 2007 17:04:16 -0000
@@ -32,6 +32,7 @@
#include <string.h>

#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>

#include <glib/gi18n.h>

@@ -41,6 +42,9 @@
#include "service.h"
#include "adapter.h"

+#define PROPERTIES_DBUS_PATH "/org/bluez/GnomeProperties"
+#define PROPERTIES_DBUS_SERVICE "org.bluez.GnomeProperties"
+
static void delete_callback(GtkWidget *window, GdkEvent *event,
gpointer user_data)
{
@@ -58,7 +62,7 @@ static void close_callback(GtkWidget *bu
gtk_main_quit();
}

-static void create_window(GtkWidget *notebook)
+static GtkWidget *create_window(GtkWidget *notebook)
{
GtkWidget *window;
GtkWidget *widget;
@@ -108,6 +112,7 @@ static void create_window(GtkWidget *not
widget, _("General"));

gtk_widget_show_all(window);
+ return window;
}

static void name_owner_changed(DBusGProxy *object, const char *name,
@@ -139,19 +144,105 @@ static DBusGProxy *setup_manager(DBusGCo
return proxy;
}

+static DBusHandlerResult MessageFunc (DBusConnection *c, DBusMessage *m, void *user_data)
+{
+ if (dbus_message_get_type(m) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
+ !strncmp(PROPERTIES_DBUS_PATH, dbus_message_get_path(m), strlen(PROPERTIES_DBUS_PATH)) &&
+ !strncmp(PROPERTIES_DBUS_SERVICE, dbus_message_get_interface(m), strlen(PROPERTIES_DBUS_SERVICE)) &&
+ !strncmp("Present", dbus_message_get_member(m), 7)) {
+ GtkWindow *window = user_data;
+ gtk_window_present(window);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusGConnection *register_instance (int *retval, gboolean singleton)
+{
+ DBusGConnection *sc;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ guint request_result;
+ gboolean ret;
+
+ sc = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL) {
+ g_printerr("Connecting to session bus failed: %s\n",
+ error->message);
+ g_error_free(error);
+ *retval = 1;
+ return NULL;
+ }
+
+ proxy = dbus_g_proxy_new_for_name(sc,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ ret = dbus_g_proxy_call(proxy, "RequestName", NULL,
+ G_TYPE_STRING, PROPERTIES_DBUS_SERVICE,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &request_result,
+ G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ if (!ret) {
+ g_printerr("Failed to request name on the session bus\n");
+ dbus_g_connection_unref(sc);
+ *retval = 1;
+ return NULL;
+ }
+
+ if (request_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && singleton) {
+ proxy = dbus_g_proxy_new_for_name(sc,
+ PROPERTIES_DBUS_SERVICE,
+ PROPERTIES_DBUS_PATH,
+ PROPERTIES_DBUS_SERVICE);
+ dbus_g_proxy_call_no_reply(proxy, "Present", G_TYPE_INVALID, G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ *retval = 0;
+
+ g_print("Another instance is already running.\n");
+ dbus_g_connection_unref(sc);
+ return NULL;
+ }
+
+ return sc;
+}
+
int main(int argc, char *argv[])
{
+ GOptionContext *ctx;
GtkWidget *notebook;
- DBusGConnection *conn;
- DBusGProxy *manager;
+ GtkWidget *window;
GError *error = NULL;
-
+ DBusGConnection *conn, *session_conn = NULL;
+ DBusGProxy *manager;
+ DBusObjectPathVTable vtable;
+ int retval = 0;
+ gboolean singleton = FALSE;
+
+ GOptionEntry entries[] = {
+ { "singleton", 0, 0, G_OPTION_ARG_NONE, &singleton,
+ N_("Only allow one instance of this application"), NULL },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);

gtk_init(&argc, &argv);

+ ctx = g_option_context_new("");
+ g_option_context_add_main_entries(ctx, entries, NULL);
+ if (!g_option_context_parse(ctx, &argc, &argv, &error)) {
+ g_printerr(_("parsing failed: %s\n"), error->message);
+ g_error_free(error);
+ g_option_context_free(ctx);
+ return retval;
+ }
+
conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
if (error != NULL) {
g_printerr("Connecting to system bus failed: %s\n",
@@ -160,15 +251,24 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}

+ session_conn = register_instance(&retval, singleton);
+ if (!session_conn)
+ exit(retval);
+
setup_general();

notebook = gtk_notebook_new();
-
+
assign_adapter(notebook);

manager = setup_manager(conn);

- create_window(notebook);
+ window = create_window(notebook);
+
+ vtable.message_function = MessageFunc;
+ vtable.unregister_function = NULL;
+ dbus_connection_register_object_path(dbus_g_connection_get_connection (session_conn),
+ "/org/bluez/GnomeProperties", &vtable, window);

gtk_main();

@@ -181,6 +281,9 @@ int main(int argc, char *argv[])
g_object_unref(manager);

dbus_g_connection_unref(conn);
+ dbus_g_connection_unref(session_conn);

+ g_option_context_free(ctx);
+
return 0;
}
Index: wizard/main.c
===================================================================
RCS file: /cvsroot/bluez/gnome/wizard/main.c,v
retrieving revision 1.23
diff -u -p -r1.23 main.c
--- wizard/main.c 15 Aug 2007 07:04:03 -0000 1.23
+++ wizard/main.c 13 Nov 2007 17:04:16 -0000
@@ -26,8 +26,10 @@
#endif

#include <string.h>
+#include <stdlib.h>

#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>

#include <glib/gi18n.h>

@@ -39,6 +41,9 @@

#include "bluetooth-device-selection.h"

+#define WIZARD_DBUS_PATH "/org/bluez/GnomeWizard"
+#define WIZARD_DBUS_SERVICE "org.bluez.GnomeWizard"
+
static BluetoothClient *client;

static gchar *address = NULL;
@@ -387,7 +392,7 @@ static void create_summary(GtkWidget *as
page_summary = vbox;
}

-static void create_wizard(void)
+static GtkWidget *create_wizard(void)
{
GtkWidget *assistant;

@@ -430,23 +435,126 @@ static void create_wizard(void)
gtk_widget_show_all(assistant);

gtk_assistant_update_buttons_state(GTK_ASSISTANT(assistant));
+ return assistant;
+}
+
+static DBusHandlerResult MessageFunc (DBusConnection *c, DBusMessage *m, void *user_data)
+{
+ if (dbus_message_get_type(m) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
+ !strncmp(WIZARD_DBUS_PATH, dbus_message_get_path(m), strlen(WIZARD_DBUS_PATH)) &&
+ !strncmp(WIZARD_DBUS_SERVICE, dbus_message_get_interface(m), strlen(WIZARD_DBUS_SERVICE)) &&
+ !strncmp("Present", dbus_message_get_member(m), 7)) {
+ GtkWindow *window = user_data;
+ gtk_window_present(window);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusGConnection *register_instance (int *retval, gboolean singleton)
+{
+ DBusGConnection *sc;
+ DBusGProxy *proxy;
+ GError *error = NULL;
+ guint request_result;
+ gboolean ret;
+
+ sc = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL) {
+ g_printerr("Connecting to session bus failed: %s\n",
+ error->message);
+ g_error_free(error);
+ *retval = 1;
+ return NULL;
+ }
+
+ proxy = dbus_g_proxy_new_for_name(sc,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ ret = dbus_g_proxy_call(proxy, "RequestName", NULL,
+ G_TYPE_STRING, WIZARD_DBUS_SERVICE,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &request_result,
+ G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ if (!ret) {
+ g_printerr("Failed to request name on the session bus\n");
+ dbus_g_connection_unref(sc);
+ *retval = 1;
+ return NULL;
+ }
+
+ if (request_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && singleton) {
+ proxy = dbus_g_proxy_new_for_name(sc,
+ WIZARD_DBUS_SERVICE,
+ WIZARD_DBUS_PATH,
+ WIZARD_DBUS_SERVICE);
+ dbus_g_proxy_call_no_reply(proxy, "Present", G_TYPE_INVALID, G_TYPE_INVALID);
+ g_object_unref(G_OBJECT(proxy));
+ *retval = 0;
+
+ g_print("Another instance is already running.\n");
+ dbus_g_connection_unref(sc);
+ return NULL;
+ }
+
+ return sc;
}

int main(int argc, char *argv[])
{
+ GOptionContext *ctx;
+ GtkWidget *window;
+ DBusGConnection *session_conn = NULL;
+ GError *error = NULL;
+ DBusObjectPathVTable vtable;
+ int retval = 0;
+ gboolean singleton = FALSE;
+
+ GOptionEntry entries[] = {
+ { "singleton", 0, 0, G_OPTION_ARG_NONE, &singleton,
+ N_("Only allow one instance of this application"), NULL },
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
+ };
+
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);

gtk_init(&argc, &argv);

+ ctx = g_option_context_new("");
+ g_option_context_add_main_entries(ctx, entries, NULL);
+ if (!g_option_context_parse(ctx, &argc, &argv, &error)) {
+ g_printerr(_("parsing failed: %s\n"), error->message);
+ g_error_free(error);
+ g_option_context_free(ctx);
+ return retval;
+ }
+
+ session_conn = register_instance(&retval, singleton);
+ if (!session_conn)
+ exit(retval);
+
client = bluetooth_client_new();

- create_wizard();
+ window = create_wizard();
+
+ vtable.message_function = MessageFunc;
+ vtable.unregister_function = NULL;
+ dbus_connection_register_object_path(dbus_g_connection_get_connection (session_conn),
+ WIZARD_DBUS_PATH, &vtable, window);

gtk_main();

g_object_unref(client);

+ dbus_g_connection_unref(session_conn);
+
+ g_option_context_free(ctx);
+
return 0;
}

[-- Attachment #3: Type: text/plain, Size: 309 bytes --]

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]