diff --git a/Makefile.am b/Makefile.am
index 7571c43..5490818 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,12 +1,7 @@
 DEF_SUBDIRS = icons lib applet properties wizard sendto docs po help
 
-if WITH_MOBLIN
-MOBLIN_DIR = moblin
-endif
-
-SUBDIRS = icons lib applet properties wizard sendto $(MOBLIN_DIR) docs po help
+SUBDIRS = icons lib applet properties wizard sendto docs po help
 
-DIST_SUBDIRS = $(DEF_SUBDIRS) moblin
 EXTRA_DIST = intltool-extract.in intltool-update.in intltool-merge.in ChangeLog.pre-2.27 gtk-doc.make mate-doc-utils.make
 
 # FIXME https://bugzilla.mate.org/show_bug.cgi?id=595675
diff --git a/applet/Makefile.am b/applet/Makefile.am
index ac11854..f82ab72 100644
--- a/applet/Makefile.am
+++ b/applet/Makefile.am
@@ -3,15 +3,15 @@ bin_PROGRAMS = mate-bluetooth-applet
 
 mate_bluetooth_applet_SOURCES = main.c notify.h notify.c agent.h agent.c
 
-mate_bluetooth_applet_LDADD = $(top_builddir)/lib/libcommon.la $(top_builddir)/lib/libmate-bluetooth.la $(APPLET_LIBS)
+mate_bluetooth_applet_LDADD = $(top_builddir)/lib/libmate-bluetooth.la $(APPLET_LIBS)
 
 noinst_PROGRAMS = test-agentdialog test-icon
 
 test_agentdialog_SOURCES = test-agentdialog.c notify.h notify.c
-test_agentdialog_LDADD = $(top_builddir)/lib/libcommon.la $(APPLET_LIBS)
+test_agentdialog_LDADD = $(top_builddir)/lib/libmate-bluetooth.la $(APPLET_LIBS)
 
 test_icon_SOURCES = test-icon.c notify.h notify.c
-test_icon_LDADD = $(top_builddir)/lib/libcommon.la $(APPLET_LIBS)
+test_icon_LDADD = $(APPLET_LIBS)
 
 AM_CFLAGS = $(APPLET_CFLAGS) $(WARN_CFLAGS) $(DISABLE_DEPRECATED) -DPKGDATADIR="\"$(pkgdatadir)\""
 
diff --git a/applet/agent.c b/applet/agent.c
index 094948b..040a825 100644
--- a/applet/agent.c
+++ b/applet/agent.c
@@ -31,10 +31,9 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
-#include <dbus/dbus-glib.h>
-
 #include <bluetooth-client.h>
 #include <bluetooth-agent.h>
+#include <bluetooth-utils.h>
 
 #include "notify.h"
 #include "agent.h"
@@ -46,24 +45,15 @@ static GList *input_list = NULL;
 
 typedef struct input_data input_data;
 struct input_data {
-	char *path;
 	char *uuid;
 	gboolean numeric;
-	DBusGProxy *device;
-	DBusGMethodInvocation *context;
+	GDBusProxy *device;
+	GDBusMethodInvocation *context;
 	GtkWidget *dialog;
 	GtkWidget *button;
 	GtkWidget *entry;
 };
 
-static gint input_compare(gconstpointer a, gconstpointer b)
-{
-	input_data *a_data = (input_data *) a;
-	input_data *b_data = (input_data *) b;
-
-	return g_ascii_strcasecmp(a_data->path, b_data->path);
-}
-
 static void input_free(input_data *input)
 {
 	gtk_widget_destroy(input->dialog);
@@ -74,7 +64,6 @@ static void input_free(input_data *input)
 		g_object_unref(input->device);
 
 	g_free(input->uuid);
-	g_free(input->path);
 	g_free(input);
 
 	if (g_list_length(input_list) == 0)
@@ -90,18 +79,12 @@ static void pin_callback(GtkWidget *dialog,
 		const char *text;
 
 		text = gtk_entry_get_text(GTK_ENTRY(input->entry));
-
-		if (input->numeric == TRUE) {
-			guint pin = atoi(text);
-			dbus_g_method_return(input->context, pin);
-		} else {
-			dbus_g_method_return(input->context, text);
-		}
+		g_dbus_method_invocation_return_value (input->context,
+						       g_variant_new ("(s)", text));
 	} else {
-		GError *error;
-		error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
-						"Pairing request rejected");
-		dbus_g_method_return_error(input->context, error);
+		g_dbus_method_invocation_return_dbus_error (input->context,
+							    "org.bluez.Error.Canceled",
+							    "User cancelled pairing");
 	}
 
 	input_free(input);
@@ -116,18 +99,18 @@ confirm_callback (GtkWidget *dialog,
 
 	if (response != GTK_RESPONSE_ACCEPT) {
 		GError *error;
-		error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
-					"Confirmation request rejected");
-		dbus_g_method_return_error(input->context, error);
+		error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
+				     "Confirmation request rejected");
+		g_dbus_method_invocation_return_gerror (input->context, error);
+		g_error_free (error);
 	} else
-		dbus_g_method_return(input->context);
+		g_dbus_method_invocation_return_value (input->context, NULL);
 
 	input_free(input);
 }
 
 static void set_trusted(input_data *input)
 {
-	GValue value = { 0 };
 	gboolean active;
 
 	if (input->device == NULL)
@@ -137,15 +120,7 @@ static void set_trusted(input_data *input)
 	if (active == FALSE)
 		return;
 
-	g_value_init (&value, G_TYPE_BOOLEAN);
-	g_value_set_boolean (&value, TRUE);
-
-	dbus_g_proxy_call (input->device, "SetProperty", NULL,
-			   G_TYPE_STRING, "Trusted",
-			   G_TYPE_VALUE, &value, G_TYPE_INVALID,
-			   G_TYPE_INVALID);
-
-	g_value_unset (&value);
+	g_object_set (input->device, "trusted", TRUE, NULL);
 }
 
 static void
@@ -157,12 +132,13 @@ auth_callback (GtkWidget *dialog,
 
 	if (response == GTK_RESPONSE_ACCEPT) {
 		set_trusted (input);
-		dbus_g_method_return(input->context);
+		g_dbus_method_invocation_return_value (input->context, NULL);
 	} else {
 		GError *error;
 		error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
 				     "Authorization request rejected");
-		dbus_g_method_return_error (input->context, error);
+		g_dbus_method_invocation_return_gerror (input->context, error);
+		g_error_free(error);
 	}
 
 	input_free(input);
@@ -208,12 +184,11 @@ static void toggled_callback(GtkWidget *button, gpointer user_data)
 }
 
 static void
-pin_dialog (DBusGProxy *adapter,
-		DBusGProxy *device,
+pin_dialog (GDBusProxy *device,
 		const char *name,
 		const char *long_name,
 		gboolean numeric,
-		DBusGMethodInvocation *context)
+		GDBusMethodInvocation *context)
 {
 	GtkWidget *dialog;
 	GtkWidget *button;
@@ -227,7 +202,6 @@ pin_dialog (DBusGProxy *adapter,
 		gtk_builder_add_from_file (xml, PKGDATADIR "/passkey-dialogue.ui", NULL);
 
 	input = g_new0 (input_data, 1);
-	input->path = g_strdup (dbus_g_proxy_get_path(adapter));
 	input->numeric = numeric;
 	input->context = context;
 	input->device = g_object_ref (device);
@@ -299,12 +273,11 @@ static void display_dialog(DBusGProxy *adapter, DBusGProxy *device,
 #endif
 
 static void
-confirm_dialog (DBusGProxy *adapter,
-		DBusGProxy *device,
+confirm_dialog (GDBusProxy *device,
 		const char *name,
 		const char *long_name,
 		const char *value,
-		DBusGMethodInvocation *context)
+		GDBusMethodInvocation *context)
 {
 	GtkWidget *dialog;
 	GtkBuilder *xml;
@@ -312,7 +285,6 @@ confirm_dialog (DBusGProxy *adapter,
 	input_data *input;
 
 	input = g_new0 (input_data, 1);
-	input->path = g_strdup (dbus_g_proxy_get_path(adapter));
 	input->device = g_object_ref (device);
 	input->context = context;
 
@@ -349,12 +321,11 @@ confirm_dialog (DBusGProxy *adapter,
 }
 
 static void
-auth_dialog (DBusGProxy *adapter,
-	     DBusGProxy *device,
+auth_dialog (GDBusProxy *device,
 	     const char *name,
 	     const char *long_name,
 	     const char *uuid,
-	     DBusGMethodInvocation *context)
+	     GDBusMethodInvocation *context)
 {
 	GtkBuilder *xml;
 	GtkWidget *dialog;
@@ -363,7 +334,6 @@ auth_dialog (DBusGProxy *adapter,
 	input_data *input;
 
 	input = g_new0 (input_data, 1);
-	input->path = g_strdup (dbus_g_proxy_get_path (adapter));
 	input->uuid = g_strdup (uuid);
 	input->device = g_object_ref (device);
 	input->context = context;
@@ -428,33 +398,24 @@ static void notification_closed(GObject *object, gpointer user_data)
 #endif
 
 static char *
-device_get_name(DBusGProxy *proxy, char **long_name)
+device_get_name(GDBusProxy *proxy, char **long_name)
 {
-	GHashTable *hash;
-	GValue *value;
+	GVariant *value = NULL;
 	char *alias, *address;
 
 	if (long_name != NULL)
 		*long_name = NULL;
 
-	if (dbus_g_proxy_call (proxy, "GetProperties",  NULL,
-			       G_TYPE_INVALID,
-			       DBUS_TYPE_G_DICTIONARY, &hash,
-			       G_TYPE_INVALID) == FALSE) {
-		return NULL;
-	}
-
-	value = g_hash_table_lookup(hash, "Address");
+	value = g_dbus_proxy_get_cached_property (proxy, "Address");
 	if (value == NULL) {
-		g_hash_table_destroy (hash);
 		return NULL;
 	}
-	address = g_value_dup_string(value);
+	address = g_variant_dup_string (value, NULL);
+	g_variant_unref (value);
 
-	value = g_hash_table_lookup(hash, "Alias");
-	alias = value ? g_value_dup_string(value) : NULL;
-
-	g_hash_table_destroy (hash);
+	value = g_dbus_proxy_get_cached_property (proxy, "Name");
+	alias = value ? g_variant_dup_string (value, NULL) : NULL;
+	g_variant_unref (value);
 
 	if (g_strcmp0 (alias, address) == 0) {
 		g_free (alias);
@@ -471,24 +432,25 @@ device_get_name(DBusGProxy *proxy, char **long_name)
 	return alias;
 }
 
-static gboolean pincode_request(DBusGMethodInvocation *context,
-					DBusGProxy *device, gpointer user_data)
+static void
+pincode_request (GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  gpointer               user_data)
 {
-	DBusGProxy *adapter = user_data;
 	char *name, *long_name, *line;
 
 	name = device_get_name (device, &long_name);
 	if (name == NULL)
-		return FALSE;
+		return;
 
-	pin_dialog(adapter, device, name, long_name, FALSE, context);
+	pin_dialog(device, name, long_name, FALSE, invocation);
 
 	g_free (long_name);
 
 	if (notification_supports_actions () == FALSE) {
 		g_free (name);
 		present_notification_dialogs ();
-		return TRUE;
+		return;
 	}
 
 	/* translators: this is a popup telling you a particular device
@@ -502,28 +464,26 @@ static gboolean pincode_request(DBusGMethodInvocation *context,
 			  G_CALLBACK(notification_closed));
 
 	g_free(line);
-
-	return TRUE;
 }
 
-static gboolean pin_request(DBusGMethodInvocation *context,
-					DBusGProxy *device, gpointer user_data)
+static void pin_request(GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  gpointer               user_data)
 {
-	DBusGProxy *adapter = user_data;
 	char *name, *long_name, *line;
 
 	name = device_get_name (device, &long_name);
 	if (name == NULL)
-		return FALSE;
+		return;
 
-	pin_dialog(adapter, device, name, long_name, TRUE, context);
+	pin_dialog(device, name, long_name, TRUE, invocation);
 
 	g_free (long_name);
 
 	if (notification_supports_actions () == FALSE) {
 		g_free (name);
 		present_notification_dialogs ();
-		return TRUE;
+		return;
 	}
 
 	/* translators: this is a popup telling you a particular device
@@ -537,19 +497,17 @@ static gboolean pin_request(DBusGMethodInvocation *context,
 			  G_CALLBACK(notification_closed));
 
 	g_free(line);
-
-	return TRUE;
 }
 
-static gboolean
-display_request (DBusGMethodInvocation *context,
-		 DBusGProxy *device,
-		 guint pin,
-		 guint entered,
-		 gpointer user_data)
+static void
+display_request (GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  guint                  pin,
+		  guint                  entered,
+		  gpointer               user_data)
 {
 	g_warning ("Not implemented, please file a bug at how this happened");
-	return FALSE;
+	return;
 #if 0
 	DBusGProxy *adapter = user_data;
 	char *name, *text;
@@ -584,21 +542,20 @@ display_request (DBusGMethodInvocation *context,
 #endif
 }
 
-static gboolean
-confirm_request (DBusGMethodInvocation *context,
-		 DBusGProxy *device,
-		 guint pin,
-		 gpointer user_data)
+static void
+confirm_request (GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  guint                  pin,
+		  gpointer               user_data)
 {
-	DBusGProxy *adapter = user_data;
 	char *name, *long_name, *line, *text;
 
 	name = device_get_name (device, &long_name);
 	if (name == NULL)
-		return FALSE;
+		return;
 
 	text = g_strdup_printf("%d", pin);
-	confirm_dialog(adapter, device, name, long_name, text, context);
+	confirm_dialog(device, name, long_name, text, invocation);
 	g_free(text);
 
 	g_free (long_name);
@@ -622,31 +579,27 @@ confirm_request (DBusGMethodInvocation *context,
 		present_notification_dialogs ();
 
 	g_free(line);
-
-	return TRUE;
 }
 
-static gboolean
-authorize_request (DBusGMethodInvocation *context,
-		   DBusGProxy *device,
-		   const char *uuid,
-		   gpointer user_data)
+static void
+authorize_request (GDBusMethodInvocation *invocation,
+		    GDBusProxy            *device,
+		    gpointer               user_data)
 {
-	DBusGProxy *adapter = user_data;
 	char *name, *long_name, *line;
 
 	name = device_get_name (device, &long_name);
 	if (name == NULL)
-		return FALSE;
+		return;
 
-	auth_dialog (adapter, device, name, long_name, uuid, context);
+	auth_dialog (device, name, long_name, NULL, invocation);
 
 	g_free (long_name);
 
 	if (notification_supports_actions () == FALSE) {
 		g_free (name);
 		present_notification_dialogs ();
-		return TRUE;
+		return;
 	}
 
 	line = g_strdup_printf (_("Authorization request from '%s'"), name);
@@ -658,92 +611,83 @@ authorize_request (DBusGMethodInvocation *context,
 			   G_CALLBACK (notification_closed));
 
 	g_free (line);
-
-	return TRUE;
 }
 
-static gboolean cancel_request(DBusGMethodInvocation *context,
-							gpointer user_data)
+static void
+authorize_service_request (GDBusMethodInvocation *invocation,
+			    GDBusProxy            *device,
+			    const char            *uuid,
+			    gpointer               user_data)
 {
-	DBusGProxy *adapter = user_data;
-	GList *list;
-	GError *result;
-	input_data *input;
-
-	input = g_new0(input_data, 1);
-	input->path = g_strdup(dbus_g_proxy_get_path(adapter));
-
-	list = g_list_find_custom(input_list, input, input_compare);
+	char *name, *long_name, *line;
 
-	g_free(input->path);
-	g_free(input);
+	name = device_get_name (device, &long_name);
+	if (name == NULL)
+		return;
 
-	if (!list || !list->data)
-		return FALSE;
+	auth_dialog (device, name, long_name, uuid, invocation);
 
-	input = list->data;
+	g_free (long_name);
 
-	close_notification();
+	if (notification_supports_actions () == FALSE) {
+		g_free (name);
+		present_notification_dialogs ();
+		return;
+	}
 
-	result = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
-						"Agent callback cancelled");
+	line = g_strdup_printf (_("Authorization request from '%s'"), name);
 
-	dbus_g_method_return_error(input->context, result);
+	g_free (name);
 
-	input_free(input);
+	show_notification (_("Bluetooth device"),
+			   line, _("Check authorization"), 0,
+			   G_CALLBACK (notification_closed));
 
-	return TRUE;
+	g_free (line);
 }
 
-static void
-default_adapter_changed (GObject    *gobject,
-			 GParamSpec *pspec,
-			 gpointer    user_data)
+static gboolean cancel_request (GDBusMethodInvocation *invocation,
+		 gpointer               user_data)
 {
-	char *adapter_str;
+	GList *l;
+	input_data *input;
 
-	g_object_get (G_OBJECT (gobject), "default-adapter", &adapter_str, NULL);
-	if (agent != NULL) {
-		bluetooth_agent_unregister (agent);
-		g_object_unref (agent);
-		agent = NULL;
+	if (!input_list) {
+		return FALSE;
 	}
-	if (adapter_str != NULL) {
-		DBusGConnection *connection;
-		DBusGProxy *adapter;
 
-		connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
-		adapter = dbus_g_proxy_new_for_name (connection,
-						     "org.bluez",
-						     adapter_str,
-						     "org.bluez.Adapter");
-		dbus_g_connection_unref (connection);
+	for (l = input_list; l; l = g_list_next(l)) {
+		input = l->data;
 
-		agent = bluetooth_agent_new();
+		g_dbus_method_invocation_return_value (input->context, NULL);
+		
+		input_free(input);
+	}
 
-		bluetooth_agent_set_pincode_func(agent, pincode_request, adapter);
-		bluetooth_agent_set_passkey_func(agent, pin_request, adapter);
-		bluetooth_agent_set_display_func(agent, display_request, adapter);
-		bluetooth_agent_set_confirm_func(agent, confirm_request, adapter);
-		bluetooth_agent_set_authorize_func(agent, authorize_request, adapter);
-		bluetooth_agent_set_cancel_func(agent, cancel_request, adapter);
+	g_list_free(input_list);
+	input_list = NULL;
 
-		bluetooth_agent_register(agent, adapter);
+	close_notification();
 
-		g_object_unref (adapter);
-	}
-	g_free (adapter_str);
+	return TRUE;
 }
 
 int setup_agents(void)
 {
-	dbus_g_error_domain_register(AGENT_ERROR, "org.bluez.Error",
-							AGENT_ERROR_TYPE);
-
 	client = bluetooth_client_new();
-	g_signal_connect (G_OBJECT (client), "notify::default-adapter",
-			  G_CALLBACK (default_adapter_changed), NULL);
-	default_adapter_changed (G_OBJECT (client), NULL, NULL);
+
+	agent = bluetooth_agent_new ();
+	bluetooth_agent_register (agent);
+
+	bluetooth_agent_set_pincode_func (agent, pincode_request, NULL);
+	bluetooth_agent_set_passkey_func (agent, pin_request, NULL);
+	bluetooth_agent_set_display_func (agent, display_request, NULL);
+	// TODO bluetooth_agent_set_display_pincode_func (agent, display_pincode_callback, NULL);
+	bluetooth_agent_set_confirm_func (agent, confirm_request, NULL);
+	bluetooth_agent_set_authorize_func (agent, authorize_request, NULL);
+	bluetooth_agent_set_authorize_service_func (agent, authorize_service_request, NULL);
+	bluetooth_agent_set_cancel_func (agent, cancel_request, NULL);
+	
 
 	return 0;
 }
diff --git a/applet/main.c b/applet/main.c
index daf6672..33ebc07 100644
--- a/applet/main.c
+++ b/applet/main.c
@@ -34,6 +34,7 @@
 #include <bluetooth-client.h>
 #include <bluetooth-client-private.h>
 #include <bluetooth-chooser.h>
+#include <bluetooth-utils.h>
 #include <bluetooth-killswitch.h>
 
 #include "notify.h"
@@ -42,6 +43,7 @@
 static gboolean option_debug = FALSE;
 static BluetoothClient *client;
 static GtkTreeModel *devices_model;
+static GCancellable *cancellable;
 static guint num_adapters_present = 0;
 static guint num_adapters_powered = 0;
 static gboolean show_icon_pref = TRUE;
@@ -268,24 +270,14 @@ set_powered_foreach (GtkTreeModel *model,
 		     GtkTreeIter  *iter,
 		     gpointer      data)
 {
-	DBusGProxy *proxy = NULL;
-	GValue value = { 0, };
+	GDBusProxy *proxy = NULL;
 
 	gtk_tree_model_get (model, iter,
 			    BLUETOOTH_COLUMN_PROXY, &proxy, -1);
 	if (proxy == NULL)
 		return FALSE;
 
-	g_value_init (&value, G_TYPE_BOOLEAN);
-	g_value_set_boolean (&value, TRUE);
-
-	dbus_g_proxy_call_no_reply (proxy, "SetProperty",
-				    G_TYPE_STRING, "Powered",
-				    G_TYPE_VALUE, &value,
-				    G_TYPE_INVALID,
-				    G_TYPE_INVALID);
-
-	g_value_unset (&value);
+	g_object_set (G_OBJECT (proxy), "powered", TRUE, NULL);
 	g_object_unref (proxy);
 
 	return FALSE;
@@ -322,7 +314,7 @@ bluetooth_discoverable_callback (GtkToggleAction *toggleaction, gpointer user_da
 
 	discoverable = gtk_toggle_action_get_active (toggleaction);
 	discover_lock = TRUE;
-	bluetooth_client_set_discoverable (client, discoverable);
+	g_object_set (G_OBJECT (client), "default-adapter-discoverable", discoverable, NULL);
 	discover_lock = FALSE;
 }
 
@@ -571,14 +563,21 @@ set_device_status_label (const char *address, int connected)
 }
 
 static void
-connection_action_callback (BluetoothClient *_client,
-			    gboolean success,
+connection_action_callback (GObject *source_object,
+			    GAsyncResult *res,
 			    gpointer user_data)
 {
 	GtkAction *action = (GtkAction *) user_data;
 	const char *address;
+	gboolean success;
+	GError *error = NULL;
 	int connected;
 
+	success = bluetooth_client_connect_service_finish (BLUETOOTH_CLIENT (source_object),
+							   res, &error);
+	if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+		goto out;
+
 	/* Revert to the previous state and wait for the
 	 * BluetoothClient to catch up */
 	connected = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "connected"));
@@ -587,12 +586,15 @@ connection_action_callback (BluetoothClient *_client,
 	else if (connected == CONNECTING)
 		connected = DISCONNECTED;
 	else
-		return;
+		goto out;
 
 	g_object_set_data_full (G_OBJECT (action),
 				"connected", GINT_TO_POINTER (connected), NULL);
 	address = g_object_get_data (G_OBJECT (action), "address");
 	set_device_status_label (address, connected);
+
+out:
+	g_clear_error (&error);
 }
 
 static void
@@ -610,11 +612,11 @@ on_connect_activate (GtkAction *action, gpointer data)
 	path = g_object_get_data (G_OBJECT (action), "device-path");
 
 	if (connected == DISCONNECTED) {
-		if (bluetooth_client_connect_service (client, path, connection_action_callback, action) != FALSE)
-			connected = DISCONNECTING;
+		bluetooth_client_connect_service (client, path, TRUE, cancellable, connection_action_callback, action);
+		connected = DISCONNECTING;
 	} else if (connected == CONNECTED) {
-		if (bluetooth_client_disconnect_service (client, path, connection_action_callback, action) != FALSE)
-			connected = CONNECTING;
+		bluetooth_client_connect_service (client, path, FALSE, cancellable, connection_action_callback, action);
+		connected = CONNECTING;
 	} else {
 		g_assert_not_reached ();
 	}
@@ -804,7 +806,7 @@ update_device_list (GtkTreeIter *parent)
 	cont = gtk_tree_model_iter_children (devices_model, &iter, parent);
 	while (cont) {
 		GHashTable *services;
-		DBusGProxy *proxy;
+		GDBusProxy *proxy;
 		char *alias, *address, **uuids, *name;
 		gboolean is_connected;
 		BluetoothType type;
@@ -979,7 +981,7 @@ update_device_list (GtkTreeIter *parent)
 			g_object_set_data_full (G_OBJECT (oper),
 						"connected", GINT_TO_POINTER (is_connected ? CONNECTED : DISCONNECTED), NULL);
 			g_object_set_data_full (G_OBJECT (oper),
-						"device-path", g_strdup (dbus_g_proxy_get_path (proxy)), g_free);
+						"device-path", g_strdup (g_dbus_proxy_get_object_path (proxy)), g_free);
 		}
 
 		/* And now for the trick of the day */
@@ -1094,8 +1096,6 @@ int main(int argc, char *argv[])
 	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
 	textdomain(GETTEXT_PACKAGE);
 
-	g_type_init ();
-
 	/* Parse command-line options */
 	context = g_option_context_new (N_("- Bluetooth applet"));
 	g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
@@ -1133,6 +1133,8 @@ int main(int argc, char *argv[])
 
 	devices_model = bluetooth_client_get_model(client);
 
+	cancellable = g_cancellable_new ();
+
 	g_signal_connect(G_OBJECT(devices_model), "row-inserted",
 			 G_CALLBACK(device_added), NULL);
 	g_signal_connect(G_OBJECT(devices_model), "row-deleted",
diff --git a/applet/test-agentdialog.c b/applet/test-agentdialog.c
index d2506d5..60cc9e8 100644
--- a/applet/test-agentdialog.c
+++ b/applet/test-agentdialog.c
@@ -32,8 +32,7 @@ static void activate_callback(GObject *widget, gpointer user_data)
 int main(int argc, char *argv[])
 {
 	GtkStatusIcon *statusicon;
-	DBusGConnection *conn;
-	DBusGProxy *adapter, *device;
+	GDBusProxy *adapter, *device;
 	GError *error = NULL;
 
 	bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
@@ -44,14 +43,6 @@ int main(int argc, char *argv[])
 
 	gtk_window_set_default_icon_name("bluetooth");
 
-	conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-	if (error != NULL) {
-		g_printerr("Connecting to system bus failed: %s\n",
-							error->message);
-		g_error_free(error);
-		return 1;
-	}
-
 	set_icon (TRUE);
 	statusicon = init_notification();
 
@@ -60,16 +51,18 @@ int main(int argc, char *argv[])
 
 	setup_agents();
 
-	adapter = dbus_g_proxy_new_for_name(conn, "org.bluez",
-						"/hci0", "org.bluez.Adapter");
+	adapter = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+	                                        NULL, "org.bluez",
+	                                        "/org/bluez/hci0", "org.bluez.Adapter", NULL, NULL);
 
-	device = dbus_g_proxy_new_from_proxy(adapter,
-			"/hci0/dev_11_22_33_44_55_66", "org.bluez.Device");
+	device = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+	                                        NULL, "org.bluez",
+	                                        "/org/bluez/hci0/dev_11_22_33_44_55_66", "org.bluez.Device1", NULL, NULL);
 
 	//display_dialog(adapter, device, "Test (00:11:22:33:44:55)", "123456", 0, NULL);
-	pin_dialog(adapter, device, "Test", "'Test' (00:11:22:33:44:55)", FALSE, NULL);
-	confirm_dialog(adapter, device, "Test", "'Test' (00:11:22:33:44:55)", "123456", NULL);
-	auth_dialog(adapter, device, "Test", "'Test' (00:11:22:33:44:55)", "UUID", NULL);
+	pin_dialog(device, "Test", "'Test' (00:11:22:33:44:55)", FALSE, NULL);
+	confirm_dialog(device, "Test", "'Test' (00:11:22:33:44:55)", "123456", NULL);
+	auth_dialog(device, "Test", "'Test' (00:11:22:33:44:55)", "UUID", NULL);
 
 	gtk_main();
 
@@ -80,7 +73,5 @@ int main(int argc, char *argv[])
 
 	cleanup_agents();
 
-	dbus_g_connection_unref(conn);
-
 	return 0;
 }
diff --git a/configure.ac b/configure.ac
index 8353db5..c04bc0b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,14 +1,15 @@
 AC_PREREQ(2.52)
 
 m4_define(matebt_version_major, 1)
-m4_define(matebt_version_minor, 6)
+m4_define(matebt_version_minor, 8)
 m4_define(matebt_version_micro, 0)
 
 AC_INIT([mate-bluetooth],
         [matebt_version_major.matebt_version_minor.matebt_version_micro],
         [http://www.mate-desktop.org])
 
-AC_CONFIG_SRCDIR([applet/main.c])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_SRCDIR([lib/bluetooth-client.c])
 AC_CONFIG_HEADERS([config.h])
 
 AM_INIT_AUTOMAKE([1.8 dist-bzip2 no-dist-gzip check-news])
@@ -20,7 +21,7 @@ AM_INIT_AUTOMAKE([1.8 dist-bzip2 no-dist-gzip check-news])
 # - If binary compatibility has been broken (eg removed or changed interfaces)
 #   change to C+1:0:0
 # - If the interface is the same as the previous version, change to C:R+1:A
-MATEBT_LT_VERSION=8:0:0
+MATEBT_LT_VERSION=13:0:0
 AC_SUBST(MATEBT_LT_VERSION)
 
 AM_MAINTAINER_MODE
@@ -69,21 +70,19 @@ fi
 AM_CONDITIONAL([ICON_UPDATE], [test -n "$UPDATE_ICON_CACHE"])
 
 GTK_REQUIRED=2.19.1
-GLIB_REQUIRED=2.25.7
-DBUS_GLIB_REQUIRED=0.74
+GLIB_REQUIRED=2.34
 NOTIFY_REQUIRED=0.7.0
 CAJA_SENDTO_REQUIRED=1.1.0
 
 dnl Requires for the properties window
 PKG_CHECK_MODULES(PROPS,
-		  dbus-glib-1 >= $DBUS_GLIB_REQUIRED
 		  glib-2.0 >= $GLIB_REQUIRED
 		  gtk+-2.0
+		  gio-2.0
 		  unique-1.0)
 
 dnl Requires for the applet
 PKG_CHECK_MODULES(APPLET,
-		  dbus-glib-1 >= $DBUS_GLIB_REQUIRED
 		  gmodule-export-2.0
 		  glib-2.0 >= $GLIB_REQUIRED
 		  gtk+-2.0 >= $GTK_REQUIRED
@@ -92,7 +91,7 @@ PKG_CHECK_MODULES(APPLET,
 
 dnl Requires for the sendto app
 PKG_CHECK_MODULES(SENDTO,
-		  dbus-glib-1 >= $DBUS_GLIB_REQUIRED
+		  glib-2.0 >= $GLIB_REQUIRED
 		  gtk+-2.0
 		  gio-2.0)
 
@@ -120,74 +119,26 @@ AM_CONDITIONAL(HAVE_NST, test "x$have_nst" = "xyes")
 
 dnl Requires for the wizard dialogue
 PKG_CHECK_MODULES(WIZARD,
-		  dbus-glib-1 >= $DBUS_GLIB_REQUIRED
 		  gmodule-export-2.0
 		  gtk+-2.0
 		  unique-1.0)
 
 dnl Requires for the input helper
-PKG_CHECK_MODULES(INPUT,
-		  xi
-		  x11
-		  gtk+-2.0)
+PKG_CHECK_MODULES(INPUT, gdk-2.0 gtk+-2.0 x11 xi)
 
 dnl Requires for the public library
+AC_CHECK_LIBM
+AC_SUBST(LIBM)
 PKG_CHECK_MODULES(LIBMATEBT,
-		  dbus-glib-1 >= $DBUS_GLIB_REQUIRED
-		  gtk+-2.0)
-
-dnl Requires for the private library
-PKG_CHECK_MODULES(COMMON,
-		  dbus-glib-1 >= $DBUS_GLIB_REQUIRED
-		  gmodule-2.0
-		  gtk+-2.0)
-
-dnl Requires for the geoclue plugin
-PKG_CHECK_MODULES(GEOCLUE,
-		  gio-2.0
-		  dbus-glib-1)
-
-dnl Requires for the plugins
-PKG_CHECK_MODULES(PLUGINS,
-		  gtk+-2.0)
-
-dnl Requires for the moblin interface
-AC_ARG_ENABLE(moblin,
-              AS_HELP_STRING([--enable-moblin=@<:@no/yes/auto@:>@],
-                             [build moblin interface]), ,
-                             enable_moblin=auto)
-
-if test "x$enable_moblin" != "xno"; then
-   PKG_CHECK_MODULES(MOBLIN,
-   [
-      dbus-glib-1,
-      gtk+-2.0,
-      mx-gtk-1.0
-      moblin-panel
-   ], have_moblin="yes", have_moblin="no")
-
-   THEME_DIR="${datadir}/${PACKAGE}/theme"
-   AS_AC_EXPAND(THEME_DIR, $THEME_DIR)
-   AC_DEFINE_UNQUOTED([THEME_DIR], "$THEME_DIR", [Carrick theme directory])
-
-   PANEL_DIR=$($PKG_CONFIG moblin-panel --variable=moblin_panel_panels_dir)
-   AC_SUBST(PANEL_DIR)
-else
-   have_moblin=no
-fi
-
-if test "x$enable_moblin" = "xyes" -a "x$have_moblin" != "xyes"; then
-   AC_MSG_ERROR([Couldn't find Moblin dependencies.])
-fi
-AM_CONDITIONAL(WITH_MOBLIN, test "x$have_moblin" = "xyes")
-
-DBUS_BINDING_TOOL="dbus-binding-tool"
-AC_SUBST(DBUS_BINDING_TOOL)
+	gmodule-2.0
+	gio-unix-2.0
+	gtk+-2.0 >= $GTK_REQUIRED
+	libudev)
 
-GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
-AC_SUBST(GLIB_GENMARSHAL)
+GDBUS_CODEGEN="gdbus-codegen"
+AC_SUBST(GDBUS_CODEGEN)
 
-GOBJECT_INTROSPECTION_CHECK([0.6.7])
+GOBJECT_INTROSPECTION_CHECK([0.9.5])
 
 MATE_COMMON_INIT
 MATE_DEBUG_CHECK
@@ -201,18 +152,12 @@ AC_OUTPUT(Makefile
 	  mate-bluetooth-1.0.pc
 	  icons/Makefile
 	  lib/Makefile
-	  lib/plugins/Makefile
 	  applet/Makefile
 	  applet/mate-bluetooth-applet.desktop.in
 	  properties/Makefile
 	  properties/mate-bluetooth-properties.desktop.in
 	  wizard/Makefile
 	  sendto/Makefile
-	  moblin/Makefile
-	  moblin/bluetooth-panel.desktop.in
-	  moblin/theme/Makefile
-	  moblin/moblin-copy-n-paste/Makefile
-	  moblin/moblin-icons/Makefile
 	  docs/Makefile
 	  docs/reference/Makefile
 	  docs/reference/libmate-bluetooth/Makefile
@@ -227,7 +172,6 @@ Configure summary:
 	Compiler....................:  ${CC}
 	Compiler Flags..............:  ${CFLAGS}
 	Prefix......................:  ${prefix}
-	Moblin interface............:  ${have_moblin}
 	caja-sendto plugin..........:  ${have_nst}
 	Documentation...............:  ${enable_gtk_doc}
 	GObject-Introspection.......:  ${found_introspection}
diff --git a/icons/Makefile.am b/icons/Makefile.am
index a1a4321..7743a3f 100644
--- a/icons/Makefile.am
+++ b/icons/Makefile.am
@@ -64,6 +64,6 @@ endif
 
 uninstall-hook:
 if ICON_UPDATE
-	$(UPDATE_ICON_CACHE) $(DESTDIR)$(datadir)/icons/mate
+	$(UPDATE_ICON_CACHE) -f -t $(DESTDIR)$(datadir)/icons/mate
 endif
 
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a24de66..24d6bc1 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,40 +1,39 @@
-SUBDIRS = plugins
-
 EXTRA_DIST = 
-BUILT_GIRSOURCES =
+CLEANFILES =
+BUILT_SOURCES =
 
-noinst_LTLIBRARIES = libcommon.la
 lib_LTLIBRARIES = libmate-bluetooth.la
 
-libcommon_la_SOURCES =						\
-		bluetooth-client.h bluetooth-client.c		\
-		bluetooth-client-private.h			\
-		bluetooth-agent.h bluetooth-agent.c		\
-		bluetooth-killswitch.h bluetooth-killswitch.c	\
-		obex-agent.h obex-agent.c			\
-		bluetooth-plugin-manager.c			\
-		bluetooth-plugin-manager.h			\
-		bluetooth-enums.h				\
-		rfkill.h
-
-libcommon_la_LIBADD = $(COMMON_LIBS)
-libcommon_la_LDFLAGS = -no-undefined $(AM_LDFLAGS)
-
-libmate_bluetooth_la_SOURCES =				\
-	bluetooth-enums.h				\
-	bluetooth-client.h bluetooth-client.c		\
-	bluetooth-client-private.h			\
-	marshal.h marshal.c				\
-	mate-bluetooth-enum-types.h			\
-	mate-bluetooth-enum-types.c			\
-	bluetooth-chooser.c bluetooth-chooser.h		\
-	bluetooth-chooser-private.h			\
-	bluetooth-filter-widget.c			\
-	bluetooth-filter-widget.h			\
-	bluetooth-chooser-button.c			\
-	bluetooth-chooser-button.h			\
-	bluetooth-chooser-combo.c			\
-	bluetooth-chooser-combo.h
+# will be scanned for introspection annotation, but won't be installed
+libmate_bluetooth_c_sources =		\
+	bluetooth-client.c		\
+	bluetooth-utils.c		\
+	bluetooth-agent.c		\
+	bluetooth-killswitch.c		\
+	mate-bluetooth-enum-types.c	\
+	bluetooth-chooser.c		\
+	bluetooth-filter-widget.c	\
+	bluetooth-chooser-button.c	\
+	bluetooth-chooser-combo.c	\
+	bluetooth-client-glue.c		\
+	bluetooth-fdo-glue.c		\
+	bluetooth-plugin-manager.c	\
+	pin.c
+
+libmate_bluetooth_private_headers =	\
+	bluetooth-client-private.h	\
+	bluetooth-agent.h		\
+	mate-bluetooth-enum-types.h	\
+	bluetooth-chooser-private.h	\
+	bluetooth-client-glue.h		\
+	bluetooth-fdo-glue.h		\
+	pin.h				\
+	rfkill.h
+
+# public headers don't need to be listed, are handled by _HEADERS
+libmate_bluetooth_la_SOURCES =			\
+	$(libmate_bluetooth_private_headers)	\
+	$(libmate_bluetooth_c_sources)
 
 libmate_bluetooth_la_LIBADD = $(LIBMATEBT_LIBS)
 
@@ -44,16 +43,29 @@ libmate_bluetooth_la_LDFLAGS =				\
 	$(AM_LDFLAGS)					\
 	-export-symbols $(srcdir)/mate-bluetooth.symbols
 
-matebluetoothdir = $(pkgincludedir)
-matebluetooth_HEADERS =				\
+libmate_bluetooth_introspect_headers =			\
 	bluetooth-client.h				\
 	bluetooth-chooser.h				\
 	bluetooth-chooser-button.h			\
+	bluetooth-chooser-combo.h			\
 	bluetooth-filter-widget.h			\
 	bluetooth-enums.h				\
+	bluetooth-utils.h				\
+	bluetooth-plugin-manager.h			\
+	bluetooth-killswitch.h
+
+matebluetoothdir = $(pkgincludedir)
+matebluetooth_HEADERS = $(libmate_bluetooth_introspect_headers)	\
 	bluetooth-plugin.h
 
-AM_CFLAGS = -I$(srcdir) $(LIBMATEBT_CFLAGS) $(COMMON_CFLAGS) $(WARN_CFLAGS) $(DISABLE_DEPRECATED) -DPLUGINDIR=\"$(libdir)/mate-bluetooth/plugins\"
+AM_CFLAGS =						\
+	-I$(srcdir)					\
+	$(LIBMATEBT_CFLAGS)				\
+	$(WARN_CFLAGS)					\
+	$(DISABLE_DEPRECATED)				\
+	-DPLUGINDIR=\"$(libdir)/mate-bluetooth/plugins\" \
+	-DPKGDATADIR="\"$(pkgdatadir)\""		\
+	-DG_LOG_DOMAIN=\"Bluetooth\"
 
 -include $(INTROSPECTION_MAKEFILE)
 INTROSPECTION_GIRS =
@@ -61,72 +73,77 @@ INTROSPECTION_SCANNER_ARGS = --warn-all --add-include-path=$(srcdir)
 INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
 
 if HAVE_INTROSPECTION
-introspection_sources = $(matebluetooth_HEADERS)
+introspection_files =				 \
+	$(libmate_bluetooth_introspect_headers) \
+	$(libmate_bluetooth_c_sources)
 
 MateBluetooth-1.0.gir: libmate-bluetooth.la
-MateBluetooth_1_0_gir_INCLUDES = GObject-2.0 Gtk-2.0 DBusGLib-1.0 GModule-2.0
-MateBluetooth_1_0_gir_CFLAGS = -I$(srcdir) $(LIBMATEBT_CFLAGS)
+MateBluetooth_1_0_gir_INCLUDES = GObject-2.0 Gtk-2.0 GModule-2.0
+MateBluetooth_1_0_gir_PACKAGES = gobject-2.0 gtk+-2.0 gmodule-2.0 glib-2.0
+MateBluetooth_1_0_gir_CFLAGS = -I$(srcdir)
 MateBluetooth_1_0_gir_LIBS = libmate-bluetooth.la
-MateBluetooth_1_0_gir_SCANNERFLAGS = --strip-prefix=Bluetooth --pkg-export=mate-bluetooth-1.0
-MateBluetooth_1_0_gir_FILES = $(introspection_sources)
+MateBluetooth_1_0_gir_SCANNERFLAGS = --symbol-prefix=bluetooth --identifier-prefix=Bluetooth --pkg-export=mate-bluetooth-1.0
+MateBluetooth_1_0_gir_FILES = $(introspection_files)
 INTROSPECTION_GIRS += MateBluetooth-1.0.gir
 
-girdir = $(INTROSPECTION_GIRDIR)
-
-EXTRA_DIST += $(BUILT_GIRSOURCES)
+girdir = $(datadir)/gir-1.0
 gir_DATA = $(INTROSPECTION_GIRS)
 
-typelibdir = $(INTROSPECTION_TYPELIBDIR)
+typelibdir = $(libdir)/girepository-1.0
 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
 
+CLEANFILES += $(gir_DATA) $(typelib_DATA)
 
 endif # HAVE_INTROSPECTION
 
-BUILT_SOURCES = marshal.h marshal.c \
-		bluetooth-client-glue.h \
-		bluetooth-agent-glue.h \
-		obex-agent-glue.h \
-		mate-bluetooth-enum-types.h \
-		mate-bluetooth-enum-types.c
+BUILT_SOURCES += bluetooth-client-glue.h \
+		 bluetooth-client-glue.c \
+		 bluetooth-fdo-glue.h \
+		 bluetooth-fdo-glue.c \
+		 mate-bluetooth-enum-types.h \
+		 mate-bluetooth-enum-types.c
 
-nodist_libcommon_la_SOURCES = $(BUILT_SOURCES)
+CLEANFILES += $(BUILT_SOURCES)
 
-CLEANFILES = $(BUILT_SOURCES) $(gir_DATA) $(typelib_DATA)
+noinst_PROGRAMS = test-client test-agent test-deviceselection test-class test-pin
 
-noinst_PROGRAMS = test-client test-agent test-deviceselection test-plugins test-class
+test_client_LDADD = libmate-bluetooth.la $(LIBMATEBT_LIBS)
 
-test_client_LDADD = libcommon.la $(GTK_LIBS) $(DBUS_LIBS)
+test_agent_LDADD = libmate-bluetooth.la $(LIBMATEBT_LIBS)
 
-test_agent_LDADD = libcommon.la $(DBUS_LIBS)
+test_deviceselection_LDADD = libmate-bluetooth.la $(LIBMATEBT_LIBS)
 
-test_deviceselection_LDADD = libcommon.la libmate-bluetooth.la
+test_class_LDADD = libmate-bluetooth.la $(LIBMATEBT_LIBS)
 
-test_plugins_LDADD = libcommon.la
+test_pin_SOURCES = test-pin.c
+test_pin_LDADD = libmate-bluetooth.la $(LIBMATEBT_LIBS)
 
-test_class_LDADD = libcommon.la
+pin_DATA = pin-code-database.xml
+pindir = $(pkgdatadir)
 
-EXTRA_DIST += marshal.list \
-		bluetooth-client.xml \
-		bluetooth-agent.xml \
-		obex-agent.xml \
-		mate-bluetooth.symbols
+pin-code-database.xml.valid: pin-code-database.xml
+	@if test -n $(XMLLINT) ; then \
+		xmllint --noout --valid $(srcdir)/pin-code-database.xml ;	\
+	fi
+	touch $@
 
-MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES += pin-code-database.xml.valid
 
-marshal.h: marshal.list
-	$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=marshal $< --header > $@
+all-local: pin-code-database.xml.valid
+
+EXTRA_DIST += bluetooth-client.xml bluetooth-fdo.xml mate-bluetooth.symbols $(pin_DATA)
+
+MAINTAINERCLEANFILES = Makefile.in
 
-marshal.c: marshal.list
-	$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=marshal $< --header --body > $@
+bluetooth-client-glue.c: bluetooth-client-glue.h
 
-bluetooth-client-glue.h: bluetooth-client.xml bluetooth-agent.h bluetooth-agent.c
-	$(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=bluetooth_client --mode=glib-client --output=$@ $<
+bluetooth-client-glue.c bluetooth-client-glue.h: bluetooth-client.xml
+	$(AM_V_GEN) $(GDBUS_CODEGEN) --c-namespace= --generate-c-code=bluetooth-client-glue --interface-prefix=org.bluez $<
 
-bluetooth-agent-glue.h: bluetooth-agent.xml bluetooth-agent.h bluetooth-agent.c
-	$(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=bluetooth_agent --mode=glib-server --output=$@ $<
+bluetooth-fdo-glue.c: bluetooth-fdo-glue.h
 
-obex-agent-glue.h: obex-agent.xml
-	$(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=obex_agent --mode=glib-server --output=$@ $<
+bluetooth-fdo-glue.c bluetooth-fdo-glue.h: bluetooth-fdo.xml
+	$(AM_V_GEN) $(GDBUS_CODEGEN) --c-namespace= --generate-c-code=bluetooth-fdo-glue --interface-prefix=org.freedesktop.DBus $<
 
 mate_bluetooth_headers_to_scan_for_enums = bluetooth-enums.h
 # Generate the enums source code, with glib-mkenums:
diff --git a/lib/bluetooth-agent.c b/lib/bluetooth-agent.c
index 52298b6..1c6c103 100644
--- a/lib/bluetooth-agent.c
+++ b/lib/bluetooth-agent.c
@@ -26,24 +26,51 @@
 #endif
 
 #include <stdio.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <gio/gio.h>
 
+#include "bluetooth-client-glue.h"
+#include "bluetooth-fdo-glue.h"
 #include "bluetooth-agent.h"
 
-#ifdef DEBUG
-#define DBG(fmt, arg...) printf("%s:%s() " fmt "\n", __FILE__, __FUNCTION__ , ## arg)
-#else
-#define DBG(fmt...)
-#endif
-
-#define BLUEZ_SERVICE	"org.bluez"
-
-#define BLUEZ_MANAGER_PATH	"/"
-#define BLUEZ_MANAGER_INTERFACE	"org.bluez.Manager"
-#define BLUEZ_DEVICE_INTERFACE	"org.bluez.Device"
-
-static DBusGConnection *connection = NULL;
+#define BLUEZ_SERVICE			"org.bluez"
+#define BLUEZ_AGENT_PATH		"/org/bluez/agent/mate"
+#define BLUEZ_MANAGER_PATH		"/"
+
+static const gchar introspection_xml[] =
+"<node name='/'>"
+"  <interface name='org.bluez.Agent1'>"
+"    <method name='Release'/>"
+"    <method name='RequestPinCode'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='s' name='pincode' direction='out'/>"
+"    </method>"
+"    <method name='RequestPasskey'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='u' name='passkey' direction='out'/>"
+"    </method>"
+"    <method name='DisplayPasskey'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='u' name='passkey' direction='in'/>"
+"      <arg type='y' name='entered' direction='in'/>"
+"    </method>"
+"    <method name='DisplayPinCode'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='s' name='pincode' direction='in'/>"
+"    </method>"
+"    <method name='RequestConfirmation'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='u' name='passkey' direction='in'/>"
+"    </method>"
+"    <method name='RequestAuthorization'>"
+"      <arg type='o' name='device' direction='in'/>"
+"    </method>"
+"    <method name='AuthorizeService'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='s' name='uuid' direction='in'/>"
+"    </method>"
+"    <method name='Cancel'/>"
+"  </interface>"
+"</node>";
 
 #define BLUETOOTH_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
 				BLUETOOTH_TYPE_AGENT, BluetoothAgentPrivate))
@@ -51,9 +78,13 @@ static DBusGConnection *connection = NULL;
 typedef struct _BluetoothAgentPrivate BluetoothAgentPrivate;
 
 struct _BluetoothAgentPrivate {
+	GDBusConnection *conn;
 	gchar *busname;
 	gchar *path;
-	DBusGProxy *adapter;
+	AgentManager1 *agent_manager;
+	GDBusNodeInfo *introspection_data;
+	guint reg_id;
+	guint watch_id;
 
 	BluetoothAgentPasskeyFunc pincode_func;
 	gpointer pincode_data;
@@ -61,6 +92,9 @@ struct _BluetoothAgentPrivate {
 	BluetoothAgentDisplayFunc display_func;
 	gpointer display_data;
 
+	BluetoothAgentDisplayPinCodeFunc display_pincode_func;
+	gpointer display_pincode_data;
+
 	BluetoothAgentPasskeyFunc passkey_func;
 	gpointer passkey_data;
 
@@ -70,273 +104,235 @@ struct _BluetoothAgentPrivate {
 	BluetoothAgentAuthorizeFunc authorize_func;
 	gpointer authorize_data;
 
+	BluetoothAgentAuthorizeServiceFunc authorize_service_func;
+	gpointer authorize_service_data;
+
 	BluetoothAgentCancelFunc cancel_func;
 	gpointer cancel_data;
 };
 
+static GDBusProxy *get_device_from_path (const char *path)
+{
+	Device1 *device;
+	device = device1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+						 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+						 BLUEZ_SERVICE,
+						 path,
+						 NULL,
+						 NULL);
+
+	return G_DBUS_PROXY(device);
+}
+
 G_DEFINE_TYPE(BluetoothAgent, bluetooth_agent, G_TYPE_OBJECT)
 
-static gboolean bluetooth_agent_request_pin_code(BluetoothAgent *agent,
-			const char *path, DBusGMethodInvocation *context)
+static gboolean bluetooth_agent_request_pincode(BluetoothAgent *agent,
+			const char *path, GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	DBusGProxy *device;
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
+	GDBusProxy *device;
 
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	if (priv->pincode_func == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
+	device = get_device_from_path(path);
+	if (device == NULL)
+		return FALSE;
 
-	if (priv->pincode_func) {
-		if (priv->adapter != NULL)
-			device = dbus_g_proxy_new_from_proxy(priv->adapter,
-						BLUEZ_DEVICE_INTERFACE, path);
-		else
-			device = NULL;
+	priv->pincode_func(invocation, device, priv->pincode_data);
 
-		result = priv->pincode_func(context, device,
-							priv->pincode_data);
+	g_object_unref(device);
 
-		if (device != NULL)
-			g_object_unref(device);
-	}
-
-	return result;
+	return TRUE;
 }
 
 static gboolean bluetooth_agent_request_passkey(BluetoothAgent *agent,
-			const char *path, DBusGMethodInvocation *context)
+			const char *path, GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	DBusGProxy *device;
-	gboolean result = FALSE;
+	GDBusProxy *device;
 
-	DBG("agent %p sender %s", agent, sender);
-
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	if (priv->passkey_func == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
+	device = get_device_from_path(path);
+	if (device == NULL)
+		return FALSE;
 
-	if (priv->passkey_func) {
-		if (priv->adapter != NULL)
-			device = dbus_g_proxy_new_from_proxy(priv->adapter,
-						BLUEZ_DEVICE_INTERFACE, path);
-		else
-			device = NULL;
+	priv->passkey_func(invocation, device, priv->passkey_data);
 
-		result = priv->passkey_func(context, device,
-							priv->passkey_data);
+	g_object_unref(device);
 
-		if (device != NULL)
-			g_object_unref(device);
-	}
-
-	return result;
+	return TRUE;
 }
 
 static gboolean bluetooth_agent_display_passkey(BluetoothAgent *agent,
 			const char *path, guint passkey, guint8 entered,
-						DBusGMethodInvocation *context)
+						GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	DBusGProxy *device;
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
+	GDBusProxy *device;
 
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	if (priv->display_func == NULL)
 		return FALSE;
-	}
-
-	g_free (sender);
 
-	if (priv->display_func) {
-		if (priv->adapter != NULL)
-			device = dbus_g_proxy_new_from_proxy(priv->adapter,
-						BLUEZ_DEVICE_INTERFACE, path);
-		else
-			device = NULL;
+	device = get_device_from_path(path);
+	if (device == NULL)
+		return FALSE;
 
-		result = priv->display_func(context, device, passkey, entered,
-							priv->display_data);
+	priv->display_func(invocation, device, passkey, entered,
+			   priv->display_data);
 
-		if (device != NULL)
-			g_object_unref(device);
-	}
+	g_object_unref(device);
 
-	return result;
+	return TRUE;
 }
 
-static gboolean bluetooth_agent_request_confirmation(BluetoothAgent *agent,
-					const char *path, guint passkey,
-						DBusGMethodInvocation *context)
+static gboolean bluetooth_agent_display_pincode(BluetoothAgent *agent,
+						const char *path, const char *pincode,
+						GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	DBusGProxy *device;
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
+	GDBusProxy *device;
 
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	if (priv->display_pincode_func == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
+	device = get_device_from_path(path);
+	if (device == NULL)
+		return FALSE;
 
-	if (priv->confirm_func) {
-		if (priv->adapter != NULL)
-			device = dbus_g_proxy_new_from_proxy(priv->adapter,
-						BLUEZ_DEVICE_INTERFACE, path);
-		else
-			device = NULL;
+	priv->display_pincode_func(invocation, device, pincode,
+				   priv->display_data);
 
-		result = priv->confirm_func(context, device, passkey,
-							priv->confirm_data);
+	g_object_unref(device);
 
-		if (device != NULL)
-			g_object_unref(device);
-	}
-
-	return result;
+	return TRUE;
 }
 
-static gboolean bluetooth_agent_authorize(BluetoothAgent *agent,
-					const char *path, const char *uuid,
-						DBusGMethodInvocation *context)
+static gboolean bluetooth_agent_request_confirmation(BluetoothAgent *agent,
+					const char *path, guint passkey,
+						GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	DBusGProxy *device;
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
+	GDBusProxy *device;
 
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	if (priv->confirm_func == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
-
-	if (priv->authorize_func) {
-		if (priv->adapter != NULL)
-			device = dbus_g_proxy_new_from_proxy(priv->adapter,
-						BLUEZ_DEVICE_INTERFACE, path);
-		else
-			device = NULL;
+	device = get_device_from_path(path);
+	if (device == NULL)
+		return FALSE;
 
-		result = priv->authorize_func(context, device, uuid,
-							priv->authorize_data);
+	priv->confirm_func(invocation, device, passkey, priv->confirm_data);
 
-		if (device != NULL)
-			g_object_unref(device);
-	}
+	g_object_unref(device);
 
-	return result;
+	return TRUE;
 }
 
-static gboolean bluetooth_agent_confirm_mode(BluetoothAgent *agent,
-			const char *mode, DBusGMethodInvocation *context)
+static gboolean bluetooth_agent_request_authorization(BluetoothAgent *agent,
+					const char *path, GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
+	GDBusProxy *device;
 
-	DBG("agent %p sender %s", agent, sender);
+	if (priv->authorize_func == NULL)
+		return FALSE;
 
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	device = get_device_from_path(path);
+	if (device == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
+	priv->authorize_func(invocation, device, priv->authorize_data);
 
-	dbus_g_method_return(context);
+	g_object_unref(device);
 
 	return TRUE;
 }
 
-static gboolean bluetooth_agent_cancel(BluetoothAgent *agent,
-						DBusGMethodInvocation *context)
+static gboolean bluetooth_agent_authorize_service(BluetoothAgent *agent,
+					const char *path, const char *uuid,
+						GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	gboolean result = FALSE;
+	GDBusProxy *device;
 
-	DBG("agent %p sender %s", agent, sender);
+	if (priv->authorize_service_func == NULL)
+		return FALSE;
 
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	device = get_device_from_path(path);
+	if (device == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
+	priv->authorize_service_func(invocation, device, uuid,
+					    priv->authorize_service_data);
 
-	if (priv->cancel_func)
-		result = priv->cancel_func(context, priv->cancel_data);
+	g_object_unref(device);
 
-	return result;
+	return TRUE;
 }
 
-static gboolean bluetooth_agent_release(BluetoothAgent *agent,
-						DBusGMethodInvocation *context)
+static gboolean bluetooth_agent_cancel(BluetoothAgent *agent,
+						GDBusMethodInvocation *invocation)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
 
-	DBG("agent %p sender %s", agent, sender);
-
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
+	if (priv->cancel_func == NULL)
 		return FALSE;
-	}
 
-	g_free (sender);
-
-	g_object_unref(agent);
+	return priv->cancel_func(invocation, priv->cancel_data);
+}
 
-	dbus_g_method_return(context);
+static void
+name_appeared_cb (GDBusConnection *connection,
+		  const gchar     *name,
+		  const gchar     *name_owner,
+		  BluetoothAgent  *agent)
+{
+	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	return TRUE;
+	g_free (priv->busname);
+	priv->busname = g_strdup (name_owner);
 }
 
-#include "bluetooth-agent-glue.h"
+static void
+name_vanished_cb (GDBusConnection *connection,
+		  const gchar     *name,
+		  BluetoothAgent  *agent)
+{
+	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
+
+	g_free (priv->busname);
+	priv->busname = NULL;
+}
 
 static void bluetooth_agent_init(BluetoothAgent *agent)
 {
-	DBG("agent %p", agent);
+	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
+
+	priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+	g_assert (priv->introspection_data);
+	priv->conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+	priv->watch_id = g_bus_watch_name_on_connection (priv->conn,
+							 BLUEZ_SERVICE,
+							 G_BUS_NAME_WATCHER_FLAGS_NONE,
+							 (GBusNameAppearedCallback) name_appeared_cb,
+							 (GBusNameVanishedCallback) name_vanished_cb,
+							 agent,
+							 NULL);
 }
 
 static void bluetooth_agent_finalize(GObject *agent)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
+	bluetooth_agent_unregister (BLUETOOTH_AGENT (agent));
 
-	if (priv->adapter != NULL) {
-		dbus_g_proxy_call(priv->adapter, "UnregisterAgent", NULL,
-					DBUS_TYPE_G_OBJECT_PATH, priv->path,
-					G_TYPE_INVALID, G_TYPE_INVALID);
-
-		g_object_unref(priv->adapter);
-		priv->adapter = NULL;
-	}
-
-	g_free(priv->path);
-	g_free(priv->busname);
+	g_bus_unwatch_name (priv->watch_id);
+	g_free (priv->busname);
+	g_dbus_node_info_unref (priv->introspection_data);
+	g_object_unref (priv->conn);
 
 	G_OBJECT_CLASS(bluetooth_agent_parent_class)->finalize(agent);
 }
@@ -344,127 +340,169 @@ static void bluetooth_agent_finalize(GObject *agent)
 static void bluetooth_agent_class_init(BluetoothAgentClass *klass)
 {
 	GObjectClass *object_class = (GObjectClass *) klass;
-	GError *error = NULL;
-
-	DBG("class %p", klass);
 
 	g_type_class_add_private(klass, sizeof(BluetoothAgentPrivate));
 
 	object_class->finalize = bluetooth_agent_finalize;
-
-	connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-
-	if (error != NULL) {
-		g_printerr("Connecting to system bus failed: %s\n",
-							error->message);
-		g_error_free(error);
-	}
-
-	dbus_g_object_type_install_info(BLUETOOTH_TYPE_AGENT,
-				&dbus_glib_bluetooth_agent_object_info);
-
-	//dbus_g_error_domain_register(AGENT_ERROR, "org.bluez.Error",
-	//						AGENT_ERROR_TYPE);
 }
 
-BluetoothAgent *bluetooth_agent_new(void)
+BluetoothAgent *
+bluetooth_agent_new (void)
 {
-	BluetoothAgent *agent;
+	return BLUETOOTH_AGENT (g_object_new (BLUETOOTH_TYPE_AGENT, NULL));
+}
 
-	agent = BLUETOOTH_AGENT(g_object_new(BLUETOOTH_TYPE_AGENT, NULL));
+static void
+handle_method_call (GDBusConnection       *connection,
+		    const gchar           *sender,
+		    const gchar           *object_path,
+		    const gchar           *interface_name,
+		    const gchar           *method_name,
+		    GVariant              *parameters,
+		    GDBusMethodInvocation *invocation,
+		    gpointer               user_data)
+{
+	BluetoothAgent *agent = (BluetoothAgent *) user_data;
+	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
+	if (g_str_equal (sender, priv->busname) == FALSE) {
+		GError *error = NULL;
+		error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
+				     "Permission Denied");
+		g_dbus_method_invocation_take_error(invocation, error);
+		return;
+	}
 
-	return agent;
+	if (g_strcmp0 (method_name, "Release") == 0) {
+		g_dbus_method_invocation_return_value (invocation, NULL);
+	} else if (g_strcmp0 (method_name, "RequestPinCode") == 0) {
+		char *path;
+		g_variant_get (parameters, "(o)", &path);
+		bluetooth_agent_request_pincode (agent, path, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "RequestPasskey") == 0) {
+		char *path;
+		g_variant_get (parameters, "(o)", &path);
+		bluetooth_agent_request_passkey (agent, path, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "DisplayPasskey") == 0) {
+		char *path;
+		guint32 passkey;
+		guint8 entered;
+
+		g_variant_get (parameters, "(ouy)", &path, &passkey, &entered);
+		bluetooth_agent_display_passkey (agent, path, passkey, entered, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "DisplayPinCode") == 0) {
+		char *path;
+		char *pincode;
+
+		g_variant_get (parameters, "(os)", &path, &pincode);
+		bluetooth_agent_display_pincode (agent, path, pincode, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "RequestConfirmation") == 0) {
+		char *path;
+		guint32 passkey;
+
+		g_variant_get (parameters, "(ou)", &path, &passkey);
+		bluetooth_agent_request_confirmation (agent, path, passkey, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "RequestAuthorization") == 0) {
+		char *path;
+
+		g_variant_get (parameters, "(o)", &path);
+		bluetooth_agent_request_authorization (agent, path, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "AuthorizeService") == 0) {
+		char *path, *uuid;
+		g_variant_get (parameters, "(os)", &path, &uuid);
+		bluetooth_agent_authorize_service (agent, path, uuid, invocation);
+		g_free (path);
+		g_free (uuid);
+	} else if (g_strcmp0 (method_name, "Cancel") == 0) {
+		bluetooth_agent_cancel (agent, invocation);
+	}
 }
 
+static const GDBusInterfaceVTable interface_vtable =
+{
+	handle_method_call,
+	NULL, /* GetProperty */
+	NULL, /* SetProperty */
+};
+
 gboolean bluetooth_agent_setup(BluetoothAgent *agent, const char *path)
 {
 	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	DBusGProxy *proxy;
-	GObject *object;
-
-	DBG("agent %p", agent);
+	GError *error = NULL;
 
-	if (priv->path != NULL)
+	if (priv->path != NULL) {
+		g_warning ("Agent already setup on '%s'", priv->path);
 		return FALSE;
+	}
 
 	priv->path = g_strdup(path);
 
-	proxy = dbus_g_proxy_new_for_name_owner(connection, BLUEZ_SERVICE,
-			BLUEZ_MANAGER_PATH, BLUEZ_MANAGER_INTERFACE, NULL);
-
-	g_free(priv->busname);
-
-	if (proxy != NULL) {
-		priv->busname = g_strdup(dbus_g_proxy_get_bus_name(proxy));
-		g_object_unref(proxy);
-	} else
-		priv->busname = NULL;
-
-	object = dbus_g_connection_lookup_g_object(connection, priv->path);
-	if (object != NULL)
-		g_object_unref(object);
-
-	dbus_g_connection_register_g_object(connection,
-						priv->path, G_OBJECT(agent));
+	priv->reg_id = g_dbus_connection_register_object (priv->conn,
+						      priv->path,
+						      priv->introspection_data->interfaces[0],
+						      &interface_vtable,
+						      agent,
+						      NULL,
+						      &error);
+	if (priv->reg_id == 0) {
+		g_warning ("Failed to register object: %s", error->message);
+		g_error_free (error);
+	}
 
 	return TRUE;
 }
 
-gboolean bluetooth_agent_register(BluetoothAgent *agent, DBusGProxy *adapter)
+gboolean bluetooth_agent_register(BluetoothAgent *agent)
 {
-	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
-	DBusGProxy *proxy;
-	GObject *object;
+	BluetoothAgentPrivate *priv;
 	GError *error = NULL;
-	gchar *path;
+	gboolean ret;
 
 	g_return_val_if_fail (BLUETOOTH_IS_AGENT (agent), FALSE);
-	g_return_val_if_fail (DBUS_IS_G_PROXY (adapter), FALSE);
 
-	DBG("agent %p", agent);
-
-	if (priv->adapter != NULL)
+	priv = BLUETOOTH_AGENT_GET_PRIVATE (agent);
+
+	priv->agent_manager = agent_manager1_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+                     G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                     BLUEZ_SERVICE, "/org/bluez", NULL, NULL);
+
+	priv->reg_id = g_dbus_connection_register_object (priv->conn,
+						      BLUEZ_AGENT_PATH,
+						      priv->introspection_data->interfaces[0],
+						      &interface_vtable,
+						      agent,
+						      NULL,
+						      &error);
+	if (priv->reg_id == 0) {
+		g_warning ("Failed to register object: %s", error->message);
+		g_error_free (error);
+		error = NULL;
 		return FALSE;
+	}
 
-	priv->adapter = g_object_ref(adapter);
-
-	path = g_path_get_basename(dbus_g_proxy_get_path(adapter));
-
-	priv->path = g_strdup_printf("/org/bluez/agent/%s", path);
-
-	g_free(path);
-
-	proxy = dbus_g_proxy_new_for_name_owner(connection,
-			dbus_g_proxy_get_bus_name(priv->adapter),
-			dbus_g_proxy_get_path(priv->adapter),
-			dbus_g_proxy_get_interface(priv->adapter), NULL);
-
-	g_free(priv->busname);
-
-	if (proxy != NULL) {
-		priv->busname = g_strdup(dbus_g_proxy_get_bus_name(proxy));
-		g_object_unref(proxy);
-	} else
-		priv->busname = g_strdup(dbus_g_proxy_get_bus_name(adapter));
-
-	object = dbus_g_connection_lookup_g_object(connection, priv->path);
-	if (object != NULL)
-		g_object_unref(object);
-
-	dbus_g_connection_register_g_object(connection,
-						priv->path, G_OBJECT(agent));
-
-	dbus_g_proxy_call(priv->adapter, "RegisterAgent", &error,
-					DBUS_TYPE_G_OBJECT_PATH, priv->path,
-					G_TYPE_STRING, "DisplayYesNo",
-					G_TYPE_INVALID, G_TYPE_INVALID);
+	ret = agent_manager1_call_register_agent_sync (priv->agent_manager,
+						       BLUEZ_AGENT_PATH,
+						       "DisplayYesNo",
+						       NULL, &error);
+	if (ret == FALSE) {
+		g_printerr ("Agent registration failed: %s\n", error->message);
+		g_error_free (error);
+		return FALSE;
+	}
 
-	if (error != NULL) {
-		g_printerr("Agent registration failed: %s\n",
-							error->message);
-		g_error_free(error);
+	ret = agent_manager1_call_request_default_agent_sync (priv->agent_manager,
+							      BLUEZ_AGENT_PATH,
+							      NULL, &error);
+	if (ret == FALSE) {
+		g_printerr ("Agent registration failed: %s\n", error->message);
+		g_error_free (error);
+		return FALSE;
 	}
 
 	return TRUE;
@@ -472,25 +510,21 @@ gboolean bluetooth_agent_register(BluetoothAgent *agent, DBusGProxy *adapter)
 
 gboolean bluetooth_agent_unregister(BluetoothAgent *agent)
 {
-	BluetoothAgentPrivate *priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
+	BluetoothAgentPrivate *priv;
 	GError *error = NULL;
 
 	g_return_val_if_fail (BLUETOOTH_IS_AGENT (agent), FALSE);
 
-	DBG("agent %p", agent);
+	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	if (priv->adapter == NULL)
+	if (priv->agent_manager == NULL)
 		return FALSE;
 
-	DBG("unregistering agent for path '%s'", priv->path);
-
-	dbus_g_proxy_call (priv->adapter, "UnregisterAgent", &error,
-			   DBUS_TYPE_G_OBJECT_PATH, priv->path,
-			   G_TYPE_INVALID, G_TYPE_INVALID);
-
-	if (error != NULL) {
+	if (agent_manager1_call_unregister_agent_sync (priv->agent_manager,
+						       BLUEZ_AGENT_PATH,
+						       NULL, &error) == FALSE) {
 		/* Ignore errors if the adapter is gone */
-		if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD) == FALSE) {
+		if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) == FALSE) {
 			g_printerr ("Agent unregistration failed: %s '%s'\n",
 				    error->message,
 				    g_quark_to_string (error->domain));
@@ -498,12 +532,20 @@ gboolean bluetooth_agent_unregister(BluetoothAgent *agent)
 		g_error_free(error);
 	}
 
-	g_object_unref(priv->adapter);
-	priv->adapter = NULL;
+	g_object_unref(priv->agent_manager);
+	priv->agent_manager = NULL;
 
 	g_free(priv->path);
 	priv->path = NULL;
 
+	g_free(priv->busname);
+	priv->busname = NULL;
+
+	if (priv->reg_id > 0) {
+		g_dbus_connection_unregister_object (priv->conn, priv->reg_id);
+		priv->reg_id = 0;
+	}
+
 	return TRUE;
 }
 
@@ -516,8 +558,6 @@ void bluetooth_agent_set_pincode_func(BluetoothAgent *agent,
 
 	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
-
 	priv->pincode_func = func;
 	priv->pincode_data = data;
 }
@@ -531,8 +571,6 @@ void bluetooth_agent_set_passkey_func(BluetoothAgent *agent,
 
 	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
-
 	priv->passkey_func = func;
 	priv->passkey_data = data;
 }
@@ -546,12 +584,23 @@ void bluetooth_agent_set_display_func(BluetoothAgent *agent,
 
 	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
-
 	priv->display_func = func;
 	priv->display_data = data;
 }
 
+void bluetooth_agent_set_display_pincode_func(BluetoothAgent *agent,
+				BluetoothAgentDisplayPinCodeFunc func, gpointer data)
+{
+	BluetoothAgentPrivate *priv;
+
+	g_return_if_fail (BLUETOOTH_IS_AGENT (agent));
+
+	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
+
+	priv->display_pincode_func = func;
+	priv->display_pincode_data = data;
+}
+
 void bluetooth_agent_set_confirm_func(BluetoothAgent *agent,
 				BluetoothAgentConfirmFunc func, gpointer data)
 {
@@ -561,8 +610,6 @@ void bluetooth_agent_set_confirm_func(BluetoothAgent *agent,
 
 	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
-
 	priv->confirm_func = func;
 	priv->confirm_data = data;
 }
@@ -576,12 +623,23 @@ void bluetooth_agent_set_authorize_func(BluetoothAgent *agent,
 
 	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
-
 	priv->authorize_func = func;
 	priv->authorize_data = data;
 }
 
+void bluetooth_agent_set_authorize_service_func(BluetoothAgent *agent,
+				BluetoothAgentAuthorizeServiceFunc func, gpointer data)
+{
+	BluetoothAgentPrivate *priv;
+
+	g_return_if_fail (BLUETOOTH_IS_AGENT (agent));
+
+	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
+
+	priv->authorize_service_func = func;
+	priv->authorize_service_data = data;
+}
+
 void bluetooth_agent_set_cancel_func(BluetoothAgent *agent,
 				BluetoothAgentCancelFunc func, gpointer data)
 {
@@ -591,8 +649,6 @@ void bluetooth_agent_set_cancel_func(BluetoothAgent *agent,
 
 	priv = BLUETOOTH_AGENT_GET_PRIVATE(agent);
 
-	DBG("agent %p", agent);
-
 	priv->cancel_func = func;
 	priv->cancel_data = data;
 }
diff --git a/lib/bluetooth-agent.h b/lib/bluetooth-agent.h
index a212ab5..9a90196 100644
--- a/lib/bluetooth-agent.h
+++ b/lib/bluetooth-agent.h
@@ -25,7 +25,7 @@
 #define __BLUETOOTH_AGENT_H
 
 #include <glib-object.h>
-#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
 
 G_BEGIN_DECLS
 
@@ -58,45 +58,69 @@ BluetoothAgent *bluetooth_agent_new(void);
 
 gboolean bluetooth_agent_setup(BluetoothAgent *agent, const char *path);
 
-gboolean bluetooth_agent_register(BluetoothAgent *agent, DBusGProxy *adapter);
+gboolean bluetooth_agent_register(BluetoothAgent *agent);
 gboolean bluetooth_agent_unregister(BluetoothAgent *agent);
 
-typedef gboolean (*BluetoothAgentPasskeyFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *device, gpointer data);
-typedef gboolean (*BluetoothAgentDisplayFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *device, guint passkey,
-						guint entered, gpointer data);
-typedef gboolean (*BluetoothAgentConfirmFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *device, guint passkey,
-								gpointer data);
-typedef gboolean (*BluetoothAgentAuthorizeFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *device, const char *uuid,
-								gpointer data);
-typedef gboolean (*BluetoothAgentCancelFunc) (DBusGMethodInvocation *context,
-								gpointer data);
-
-void bluetooth_agent_set_pincode_func(BluetoothAgent *agent,
-				BluetoothAgentPasskeyFunc func, gpointer data);
-void bluetooth_agent_set_passkey_func(BluetoothAgent *agent,
-				BluetoothAgentPasskeyFunc func, gpointer data);
-void bluetooth_agent_set_display_func(BluetoothAgent *agent,
-				BluetoothAgentDisplayFunc func, gpointer data);
-void bluetooth_agent_set_confirm_func(BluetoothAgent *agent,
-				BluetoothAgentConfirmFunc func, gpointer data);
-void bluetooth_agent_set_authorize_func(BluetoothAgent *agent,
-				BluetoothAgentAuthorizeFunc func, gpointer data);
-void bluetooth_agent_set_cancel_func(BluetoothAgent *agent,
-				BluetoothAgentCancelFunc func, gpointer data);
+typedef void (*BluetoothAgentPasskeyFunc) (GDBusMethodInvocation *invocation,
+					   GDBusProxy            *device,
+					   gpointer               data);
+typedef void (*BluetoothAgentDisplayFunc) (GDBusMethodInvocation *invocation,
+					   GDBusProxy            *device,
+					   guint                  passkey,
+					   guint                  entered,
+					   gpointer               data);
+typedef void (*BluetoothAgentDisplayPinCodeFunc) (GDBusMethodInvocation *invocation,
+						  GDBusProxy            *device,
+						  const char            *pincode,
+						  gpointer               data);
+typedef void (*BluetoothAgentConfirmFunc) (GDBusMethodInvocation *invocation,
+					   GDBusProxy            *device,
+					   guint                  passkey,
+					   gpointer               data);
+typedef void (*BluetoothAgentAuthorizeFunc) (GDBusMethodInvocation *invocation,
+					     GDBusProxy            *device,
+					     gpointer               data);
+typedef void (*BluetoothAgentAuthorizeServiceFunc) (GDBusMethodInvocation *invocation,
+						    GDBusProxy            *device,
+						    const char            *uuid,
+						    gpointer               data);
+typedef gboolean (*BluetoothAgentCancelFunc) (GDBusMethodInvocation *invocation,
+					      gpointer               data);
+
+void bluetooth_agent_set_pincode_func (BluetoothAgent            *agent,
+				       BluetoothAgentPasskeyFunc  func,
+				       gpointer                   data);
+void bluetooth_agent_set_passkey_func (BluetoothAgent            *agent,
+				       BluetoothAgentPasskeyFunc  func,
+				       gpointer                   data);
+void bluetooth_agent_set_display_func (BluetoothAgent            *agent,
+				       BluetoothAgentDisplayFunc  func,
+				       gpointer                   data);
+void bluetooth_agent_set_display_pincode_func (BluetoothAgent                   *agent,
+					       BluetoothAgentDisplayPinCodeFunc  func,
+					       gpointer                          data);
+void bluetooth_agent_set_confirm_func (BluetoothAgent            *agent,
+				       BluetoothAgentConfirmFunc  func,
+				       gpointer                   data);
+void bluetooth_agent_set_authorize_func (BluetoothAgent              *agent,
+					 BluetoothAgentAuthorizeFunc  func,
+					 gpointer                     data);
+void bluetooth_agent_set_authorize_service_func (BluetoothAgent                     *agent,
+						 BluetoothAgentAuthorizeServiceFunc  func,
+						 gpointer                            data);
+void bluetooth_agent_set_cancel_func (BluetoothAgent           *agent,
+				      BluetoothAgentCancelFunc  func,
+				      gpointer                  data);
 
 #define AGENT_ERROR (bluetooth_agent_error_quark())
-#define AGENT_ERROR_TYPE (bluetooth_agent_error_get_type()) 
+#define AGENT_ERROR_TYPE (bluetooth_agent_error_get_type())
 
 typedef enum {
 	AGENT_ERROR_REJECT
 } AgentError;
 
-GType bluetooth_agent_error_get_type(void);
-GQuark bluetooth_agent_error_quark(void);
+GType  bluetooth_agent_error_get_type (void);
+GQuark bluetooth_agent_error_quark    (void);
 
 G_END_DECLS
 
diff --git a/lib/bluetooth-agent.xml b/lib/bluetooth-agent.xml
deleted file mode 100644
index 478177c..0000000
--- a/lib/bluetooth-agent.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/">
-  <interface name="org.bluez.Agent">
-    <method name="RequestPinCode">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="device"/>
-      <arg type="s" name="pincode" direction="out"/>
-    </method>
-
-    <method name="RequestPasskey">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="device"/>
-      <arg type="u" name="passkey" direction="out"/>
-    </method>
-
-    <method name="DisplayPasskey">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="device"/>
-      <arg type="u" name="passkey"/>
-      <arg type="y" name="entered"/>
-    </method>
-
-    <method name="RequestConfirmation">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="device"/>
-      <arg type="u" name="passkey"/>
-    </method>
-
-    <method name="Authorize">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="device"/>
-      <arg type="s" name="uuid"/>
-    </method>
-
-    <method name="ConfirmMode">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="s" name="mode"/>
-    </method>
-
-    <method name="Cancel">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-    </method>
-
-    <method name="Release">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-    </method>
-  </interface>
-</node>
diff --git a/lib/bluetooth-chooser-button.c b/lib/bluetooth-chooser-button.c
index 1916ea9..fbc9167 100644
--- a/lib/bluetooth-chooser-button.c
+++ b/lib/bluetooth-chooser-button.c
@@ -38,7 +38,7 @@
 #include "bluetooth-chooser-button.h"
 #include "bluetooth-client.h"
 #include "bluetooth-chooser.h"
-#include "marshal.h"
+#include "bluetooth-utils.h"
 
 struct _BluetoothChooserButton {
 	GtkButton          parent;
@@ -87,7 +87,7 @@ set_btdevname (BluetoothChooserButton *button, const char *bdaddr, const char *n
 		GtkTreeIter iter;
 		gboolean cont = FALSE;
 
-		model = bluetooth_client_get_device_model (button->client, NULL);
+		model = bluetooth_client_get_device_model (button->client);
 		if (model != NULL) {
 			cont = gtk_tree_model_iter_children (GTK_TREE_MODEL(model),
 							     &iter, NULL);
diff --git a/lib/bluetooth-chooser-button.h b/lib/bluetooth-chooser-button.h
index 2cf093e..363738b 100644
--- a/lib/bluetooth-chooser-button.h
+++ b/lib/bluetooth-chooser-button.h
@@ -13,9 +13,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __BLUETOOTH_CHOOSER_BUTTON_H__
@@ -29,13 +27,21 @@ G_BEGIN_DECLS
 #define BLUETOOTH_CHOOSER_BUTTON(obj)     (G_TYPE_CHECK_INSTANCE_CAST ((obj), BLUETOOTH_TYPE_CHOOSER_BUTTON, BluetoothChooserButton))
 #define BLUETOOTH_IS_CHOOSER_BUTTON(obj)  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BLUETOOTH_TYPE_CHOOSER_BUTTON))
 
+/**
+ * BluetoothChooserButton:
+ *
+ * The <structname>BluetoothChooserButton</structname> struct contains
+ * only private fields and should not be directly accessed.
+ */
 typedef struct _BluetoothChooserButton BluetoothChooserButton;
 
-typedef struct _BluetoothChooserButtonClass {
+typedef struct _BluetoothChooserButtonClass BluetoothChooserButtonClass;
+
+struct _BluetoothChooserButtonClass {
   GtkButtonClass parent_class;
 
   void (*chooser_created) (BluetoothChooserButton *self, GtkWidget *chooser);
-} BluetoothChooserButtonClass;
+};
 
 GType		bluetooth_chooser_button_get_type	(void);
 
diff --git a/lib/bluetooth-chooser-combo.c b/lib/bluetooth-chooser-combo.c
index 26b684c..7357c7f 100644
--- a/lib/bluetooth-chooser-combo.c
+++ b/lib/bluetooth-chooser-combo.c
@@ -29,7 +29,7 @@
 #include "bluetooth-client.h"
 #include "bluetooth-chooser.h"
 #include "bluetooth-chooser-private.h"
-#include "marshal.h"
+#include "bluetooth-utils.h"
 
 struct _BluetoothChooserCombo {
 	GtkVBox            parent;
diff --git a/lib/bluetooth-chooser-private.h b/lib/bluetooth-chooser-private.h
index aa17a6b..19f549d 100644
--- a/lib/bluetooth-chooser-private.h
+++ b/lib/bluetooth-chooser-private.h
@@ -26,13 +26,11 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include <dbus/dbus-glib.h>
 #include <bluetooth-enums.h>
 
 G_BEGIN_DECLS
 
 GtkTreeModel *bluetooth_chooser_get_model (BluetoothChooser *self);
-GtkTreeViewColumn *bluetooth_chooser_get_type_column (BluetoothChooser *self);
 GtkWidget *bluetooth_chooser_get_treeview (BluetoothChooser *self);
 gboolean bluetooth_chooser_remove_selected_device (BluetoothChooser *self);
 
diff --git a/lib/bluetooth-chooser.c b/lib/bluetooth-chooser.c
index 269f957..cace06c 100644
--- a/lib/bluetooth-chooser.c
+++ b/lib/bluetooth-chooser.c
@@ -26,7 +26,7 @@
  * SECTION:bluetooth-chooser
  * @short_description: a Bluetooth chooser widget
  * @stability: Stable
- * @include: bluetooth-plugin.h
+ * @include: bluetooth-chooser.h
  *
  * A tree-like widget used to select Bluetooth devices.
  **/
@@ -41,11 +41,15 @@
 
 #include "bluetooth-client.h"
 #include "bluetooth-client-private.h"
+#include "bluetooth-client-glue.h"
+#include "bluetooth-utils.h"
 #include "bluetooth-chooser.h"
 #include "bluetooth-chooser-private.h"
 #include "mate-bluetooth-enum-types.h"
 #include "bluetooth-filter-widget.h"
 
+#define BLUEZ_SERVICE	"org.bluez"
+
 enum {
 	SELECTED_DEVICE_CHANGED,
 	LAST_SIGNAL
@@ -192,8 +196,8 @@ bluetooth_chooser_start_discovery (BluetoothChooser *self)
 
 	g_return_if_fail (priv->show_searching);
 
-	if (bluetooth_client_start_discovery (priv->client) != FALSE)
-		set_search_label (self, TRUE);
+	g_object_set (G_OBJECT (priv->client), "default-adapter-discovering", TRUE, NULL);
+	set_search_label (self, TRUE);
 	priv->disco_rq = TRUE;
 }
 
@@ -211,7 +215,7 @@ bluetooth_chooser_stop_discovery (BluetoothChooser *self)
 	g_return_if_fail (priv->show_searching);
 
 	priv->disco_rq = FALSE;
-	bluetooth_client_stop_discovery (priv->client);
+	g_object_set (G_OBJECT (priv->client), "default-adapter-discovering", FALSE, NULL);
 }
 
 static char *
@@ -401,9 +405,10 @@ bluetooth_chooser_remove_selected_device (BluetoothChooser *self)
 	BluetoothChooserPrivate *priv = BLUETOOTH_CHOOSER_GET_PRIVATE(self);
 	GtkTreeIter iter;
 	gboolean ret = FALSE;
-	GError *err = NULL;
-	gchar *name;
-	DBusGProxy *device, *adapter;
+	GError *error = NULL;
+	gchar *adapter, *name;
+	GDBusProxy *device;
+	Adapter1 *adapter_proxy;
 
 	if (gtk_tree_selection_get_selected (priv->selection, NULL, &iter) == FALSE)
 		return FALSE;
@@ -412,19 +417,30 @@ bluetooth_chooser_remove_selected_device (BluetoothChooser *self)
 			    BLUETOOTH_COLUMN_PROXY, &device,
 			    BLUETOOTH_COLUMN_ALIAS, &name, -1);
 
-	adapter = bluetooth_client_get_default_adapter(priv->client);
+	g_object_get (G_OBJECT (priv->client), "default-adapter", &adapter, NULL);
+	adapter_proxy = adapter1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+						       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+						       BLUEZ_SERVICE,
+						       adapter,
+						       NULL,
+						       &error);
+	g_free (adapter);
+	if (adapter_proxy == NULL) {
+		g_warning ("Failed to create a GDBusProxy for the default adapter: %s", error->message);
+		g_error_free (error);
+		return FALSE;
+	}
 
 	if (show_confirm_dialog (self, name) != FALSE) {
 		const gchar *device_path;
 
-		device_path = dbus_g_proxy_get_path (device);
+		device_path = g_dbus_proxy_get_object_path (device);
 
-		if (dbus_g_proxy_call (adapter, "RemoveDevice", &err,
-				       DBUS_TYPE_G_OBJECT_PATH, device_path,
-				       G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
+		if (adapter1_call_remove_device_sync (adapter_proxy, device_path,
+						  NULL, &error) == FALSE) {
 			g_warning ("Failed to remove device %s: %s", name,
-				   err->message);
-			g_error_free (err);
+				   error->message);
+			g_error_free (error);
 		} else {
 			ret = TRUE;
 		}
@@ -451,22 +467,6 @@ bluetooth_chooser_get_model (BluetoothChooser *self)
 }
 
 /**
- * bluetooth_chooser_get_type_column:
- * @self: A #BluetoothChooser widget.
- *
- * Returns a #GtkTreeViewColumn object to the type column of the #BluetoothChooser.
- *
- * Return value: a #GtkTreeViewColumn object.
- **/
-GtkTreeViewColumn *
-bluetooth_chooser_get_type_column (BluetoothChooser *self)
-{
-	BluetoothChooserPrivate *priv = BLUETOOTH_CHOOSER_GET_PRIVATE(self);
-
-	return gtk_tree_view_get_column (GTK_TREE_VIEW (priv->treeview), 1);
-}
-
-/**
  * bluetooth_chooser_get_treeview:
  * @self: A #BluetoothChooser widget.
  *
@@ -697,7 +697,7 @@ static void default_adapter_changed (GObject    *gobject,
 
 	g_free (adapter);
 
-	priv->model = bluetooth_client_get_device_model (priv->client, NULL);
+	priv->model = bluetooth_client_get_device_model (priv->client);
 	if (priv->model) {
 		priv->filter = gtk_tree_model_filter_new (priv->model, NULL);
 		gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter),
@@ -791,7 +791,7 @@ create_treeview (BluetoothChooser *self)
 			  G_CALLBACK(select_browse_device_callback), self);
 
 	/* Set the model, and filter */
-	priv->model = bluetooth_client_get_device_model (priv->client, NULL);
+	priv->model = bluetooth_client_get_device_model (priv->client);
 	if (priv->model) {
 		priv->filter = gtk_tree_model_filter_new (priv->model, NULL);
 		gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter),
@@ -934,7 +934,7 @@ bluetooth_chooser_finalize (GObject *object)
 		g_signal_handler_disconnect (G_OBJECT(priv->client), priv->default_adapter_changed_id);
 		priv->default_adapter_changed_id = 0;
 
-		bluetooth_client_stop_discovery (priv->client);
+		g_object_set (G_OBJECT (priv->client), "default-adapter-discovering", FALSE, NULL);
 		g_object_unref (priv->client);
 		priv->client = NULL;
 	}
diff --git a/lib/bluetooth-client-private.h b/lib/bluetooth-client-private.h
index 8a47ddf..ce8b399 100644
--- a/lib/bluetooth-client-private.h
+++ b/lib/bluetooth-client-private.h
@@ -26,48 +26,35 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include <dbus/dbus-glib.h>
 #include <bluetooth-enums.h>
 
 G_BEGIN_DECLS
 
-guint bluetooth_class_to_type (guint32 class);
-
-DBusGProxy *bluetooth_client_get_default_adapter(BluetoothClient *client);
-
-gboolean bluetooth_client_start_discovery(BluetoothClient *client);
-gboolean bluetooth_client_stop_discovery(BluetoothClient *client);
-gboolean bluetooth_client_set_discoverable (BluetoothClient *client,
-					    gboolean discoverable);
-
-typedef void (*BluetoothClientCreateDeviceFunc) (BluetoothClient *client,
-						 const char *path,
-						 const GError *error,
-						 gpointer data);
-
-gboolean bluetooth_client_create_device(BluetoothClient *client,
-			const char *address, const char *agent,
-			BluetoothClientCreateDeviceFunc func, gpointer data);
+typedef void (*BluetoothClientSetupFunc) (BluetoothClient *client,
+					  const GError    *error,
+					  const char      *device_path);
+
+void bluetooth_client_setup_device (BluetoothClient          *client,
+				    const char               *path,
+				    gboolean                  pair,
+				    GCancellable             *cancellable,
+				    GAsyncReadyCallback       callback,
+				    gpointer                  user_data);
+gboolean bluetooth_client_setup_device_finish (BluetoothClient  *client,
+					       GAsyncResult     *res,
+					       char            **path,
+					       GError          **error);
 
 gboolean bluetooth_client_set_trusted(BluetoothClient *client,
 					const char *device, gboolean trusted);
 
-typedef void (*BluetoothClientConnectFunc) (BluetoothClient *client,
-					    gboolean success,
-					    gpointer data);
-
-gboolean bluetooth_client_connect_service(BluetoothClient *client,
-					  const char *device,
-					  BluetoothClientConnectFunc func,
-					  gpointer data);
-gboolean bluetooth_client_disconnect_service (BluetoothClient *client,
-					      const char *device,
-					      BluetoothClientConnectFunc func,
-					      gpointer data);
+GDBusProxy *bluetooth_client_get_device (BluetoothClient *client,
+					 const char      *path);
 
 void bluetooth_client_dump_device (GtkTreeModel *model,
-				   GtkTreeIter *iter,
-				   gboolean recurse);
+				   GtkTreeIter *iter);
+
+gboolean bluetooth_client_get_connectable(const char **uuids);
 
 G_END_DECLS
 
diff --git a/lib/bluetooth-client.c b/lib/bluetooth-client.c
index 3c6e605..a219074 100644
--- a/lib/bluetooth-client.c
+++ b/lib/bluetooth-client.c
@@ -3,6 +3,8 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2010       Giovanni Campagna <scampa.giovanni@gmail.com>
+ *  Copyright (C) 2013       Intel Corporation.
  *
  *
  *  This library is free software; you can redistribute it and/or
@@ -39,57 +41,19 @@
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 
-#include <dbus/dbus-glib.h>
-
 #include "bluetooth-client.h"
 #include "bluetooth-client-private.h"
 #include "bluetooth-client-glue.h"
+#include "bluetooth-fdo-glue.h"
+#include "bluetooth-utils.h"
 #include "mate-bluetooth-enum-types.h"
+#include "pin.h"
 
-#include "marshal.h"
-
-#ifdef DEBUG
-#define DBG(fmt, arg...) printf("%s:%s() " fmt "\n", __FILE__, __FUNCTION__ , ## arg)
-#else
-#define DBG(fmt...)
-#endif
-
-#ifndef DBUS_TYPE_G_OBJECT_PATH_ARRAY
-#define DBUS_TYPE_G_OBJECT_PATH_ARRAY \
-	(dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
-#endif
-
-#ifndef DBUS_TYPE_G_DICTIONARY
-#define DBUS_TYPE_G_DICTIONARY \
-	(dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
-#endif
-
-#define BLUEZ_SERVICE	"org.bluez"
-
-#define BLUEZ_MANAGER_PATH	"/"
-#define BLUEZ_MANAGER_INTERFACE	"org.bluez.Manager"
-#define BLUEZ_ADAPTER_INTERFACE	"org.bluez.Adapter"
-#define BLUEZ_DEVICE_INTERFACE	"org.bluez.Device"
-
-static char * detectable_interfaces[] = {
-	"org.bluez.Headset",
-	"org.bluez.AudioSink",
-	"org.bluez.Audio",
-	"org.bluez.Input"
-};
-
-static char * connectable_interfaces[] = {
-	"org.bluez.Audio",
-	"org.bluez.Input"
-};
-
-/* Keep in sync with above */
-#define BLUEZ_INPUT_INTERFACE	(connectable_interfaces[1])
-#define BLUEZ_AUDIO_INTERFACE (connectable_interfaces[0])
-#define BLUEZ_HEADSET_INTERFACE (detectable_interfaces[0])
-#define BLUEZ_AUDIOSINK_INTERFACE (detectable_interfaces[1])
-
-static DBusGConnection *connection = NULL;
+#define BLUEZ_SERVICE			"org.bluez"
+#define BLUEZ_MANAGER_PATH		"/"
+#define BLUEZ_ADAPTER_INTERFACE		"org.bluez.Adapter1"
+#define BLUEZ_DEVICE_INTERFACE		"org.bluez.Device1"
+#define FDO_PROPERTIES_INTERFACE	"org.freedesktop.DBus.Properties"
 
 #define BLUETOOTH_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
 				BLUETOOTH_TYPE_CLIENT, BluetoothClientPrivate))
@@ -97,172 +61,41 @@ static DBusGConnection *connection = NULL;
 typedef struct _BluetoothClientPrivate BluetoothClientPrivate;
 
 struct _BluetoothClientPrivate {
-	DBusGProxy *dbus;
-	DBusGProxy *manager;
+	guint owner_change_id;
+	ObjectManager *manager;
 	GtkTreeStore *store;
-	char *default_adapter;
-	gboolean default_adapter_powered;
+	GtkTreeRowReference *default_adapter;
 };
 
 enum {
 	PROP_0,
 	PROP_DEFAULT_ADAPTER,
 	PROP_DEFAULT_ADAPTER_POWERED,
+	PROP_DEFAULT_ADAPTER_DISCOVERABLE,
+	PROP_DEFAULT_ADAPTER_NAME,
+	PROP_DEFAULT_ADAPTER_DISCOVERING
 };
 
-G_DEFINE_TYPE(BluetoothClient, bluetooth_client, G_TYPE_OBJECT)
-
-/**
- * bluetooth_type_to_string:
- * @type: a #BluetoothType
- *
- * Returns the string representation of the @type passed. Do not free the return value.
- *
- * Return value: a string.
- **/
-const gchar *bluetooth_type_to_string(BluetoothType type)
-{
-	switch (type) {
-	case BLUETOOTH_TYPE_ANY:
-		return _("All types");
-	case BLUETOOTH_TYPE_PHONE:
-		return _("Phone");
-	case BLUETOOTH_TYPE_MODEM:
-		return _("Modem");
-	case BLUETOOTH_TYPE_COMPUTER:
-		return _("Computer");
-	case BLUETOOTH_TYPE_NETWORK:
-		return _("Network");
-	case BLUETOOTH_TYPE_HEADSET:
-		/* translators: a hands-free headset, a combination of a single speaker with a microphone */
-		return _("Headset");
-	case BLUETOOTH_TYPE_HEADPHONES:
-		return _("Headphones");
-	case BLUETOOTH_TYPE_OTHER_AUDIO:
-		return _("Audio device");
-	case BLUETOOTH_TYPE_KEYBOARD:
-		return _("Keyboard");
-	case BLUETOOTH_TYPE_MOUSE:
-		return _("Mouse");
-	case BLUETOOTH_TYPE_CAMERA:
-		return _("Camera");
-	case BLUETOOTH_TYPE_PRINTER:
-		return _("Printer");
-	case BLUETOOTH_TYPE_JOYPAD:
-		return _("Joypad");
-	case BLUETOOTH_TYPE_TABLET:
-		return _("Tablet");
-	case BLUETOOTH_TYPE_VIDEO:
-		return _("Video device");
-	default:
-		return _("Unknown");
-	}
-}
-
-/**
- * bluetooth_verify_address:
- * @bdaddr: a string representing a Bluetooth address
- *
- * Returns whether the string is a valid Bluetooth address. This does not contact the device in any way.
- *
- * Return value: %TRUE if the address is valid, %FALSE if not.
- **/
-gboolean
-bluetooth_verify_address (const char *bdaddr)
-{
-	gboolean retval = TRUE;
-	char **elems;
-	guint i;
-
-	g_return_val_if_fail (bdaddr != NULL, FALSE);
-
-	if (strlen (bdaddr) != 17)
-		return FALSE;
-
-	elems = g_strsplit (bdaddr, ":", -1);
-	if (elems == NULL)
-		return FALSE;
-	if (g_strv_length (elems) != 6) {
-		g_strfreev (elems);
-		return FALSE;
-	}
-	for (i = 0; i < 6; i++) {
-		if (strlen (elems[i]) != 2 ||
-		    g_ascii_isxdigit (elems[i][0]) == FALSE ||
-		    g_ascii_isxdigit (elems[i][1]) == FALSE) {
-			retval = FALSE;
-			break;
-		}
-	}
-
-	g_strfreev (elems);
-	return retval;
-}
+enum {
+	DEVICE_REMOVED,
+	LAST_SIGNAL
+};
 
-guint
-bluetooth_class_to_type (guint32 class)
-{
-	switch ((class & 0x1f00) >> 8) {
-	case 0x01:
-		return BLUETOOTH_TYPE_COMPUTER;
-	case 0x02:
-		switch ((class & 0xfc) >> 2) {
-		case 0x01:
-		case 0x02:
-		case 0x03:
-		case 0x05:
-			return BLUETOOTH_TYPE_PHONE;
-		case 0x04:
-			return BLUETOOTH_TYPE_MODEM;
-		}
-		break;
-	case 0x03:
-		return BLUETOOTH_TYPE_NETWORK;
-	case 0x04:
-		switch ((class & 0xfc) >> 2) {
-		case 0x01:
-		case 0x02:
-			return BLUETOOTH_TYPE_HEADSET;
-		case 0x06:
-			return BLUETOOTH_TYPE_HEADPHONES;
-		case 0x0b: /* VCR */
-		case 0x0c: /* Video Camera */
-		case 0x0d: /* Camcorder */
-			return BLUETOOTH_TYPE_VIDEO;
-		default:
-			return BLUETOOTH_TYPE_OTHER_AUDIO;
-		}
-		break;
-	case 0x05:
-		switch ((class & 0xc0) >> 6) {
-		case 0x00:
-			switch ((class & 0x1e) >> 2) {
-			case 0x01:
-			case 0x02:
-				return BLUETOOTH_TYPE_JOYPAD;
-			}
-			break;
-		case 0x01:
-			return BLUETOOTH_TYPE_KEYBOARD;
-		case 0x02:
-			switch ((class & 0x1e) >> 2) {
-			case 0x05:
-				return BLUETOOTH_TYPE_TABLET;
-			default:
-				return BLUETOOTH_TYPE_MOUSE;
-			}
-		}
-		break;
-	case 0x06:
-		if (class & 0x80)
-			return BLUETOOTH_TYPE_PRINTER;
-		if (class & 0x20)
-			return BLUETOOTH_TYPE_CAMERA;
-		break;
-	}
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static const char *connectable_uuids[] = {
+	"HSP",
+	"AudioSource",
+	"AudioSink",
+	"A/V_RemoteControlTarget",
+	"A/V_RemoteControl",
+	"Headset_-_AG",
+	"Handsfree",
+	"HandsfreeAudioGateway",
+	"HumanInterfaceDeviceService",
+};
 
-	return 0;
-}
+G_DEFINE_TYPE(BluetoothClient, bluetooth_client, G_TYPE_OBJECT)
 
 typedef gboolean (*IterSearchFunc) (GtkTreeStore *store,
 				GtkTreeIter *iter, gpointer user_data);
@@ -303,14 +136,14 @@ static gboolean compare_path(GtkTreeStore *store,
 					GtkTreeIter *iter, gpointer user_data)
 {
 	const gchar *path = user_data;
-	DBusGProxy *object;
+	GDBusProxy *object;
 	gboolean found = FALSE;
 
 	gtk_tree_model_get(GTK_TREE_MODEL(store), iter,
 					BLUETOOTH_COLUMN_PROXY, &object, -1);
 
 	if (object != NULL) {
-		found = g_str_equal(path, dbus_g_proxy_get_path(object));
+		found = g_str_equal(path, g_dbus_proxy_get_object_path(object));
 		g_object_unref(object);
 	}
 
@@ -345,17 +178,17 @@ get_iter_from_path (GtkTreeStore *store,
 static gboolean
 get_iter_from_proxy(GtkTreeStore *store,
 		    GtkTreeIter *iter,
-		    DBusGProxy *proxy)
+		    GDBusProxy *proxy)
 {
 	return iter_search(store, iter, NULL, compare_path,
-			   (gpointer) dbus_g_proxy_get_path (proxy));
+			   (gpointer) g_dbus_proxy_get_object_path (proxy));
 }
 
 static gboolean
 get_iter_from_address (GtkTreeStore *store,
 		       GtkTreeIter  *iter,
 		       const char   *address,
-		       DBusGProxy   *adapter)
+		       GDBusProxy   *adapter)
 {
 	GtkTreeIter parent_iter;
 
@@ -365,616 +198,559 @@ get_iter_from_address (GtkTreeStore *store,
 	return iter_search (store, iter, &parent_iter, compare_address, (gpointer) address);
 }
 
-static void
-device_services_changed (DBusGProxy *iface, const char *property,
-			 GValue *value, gpointer user_data)
-{
-	BluetoothClient *client = user_data;
-	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	GtkTreeIter iter;
-	GtkTreePath *tree_path;
-	GHashTable *table;
-	const char *path;
-	BluetoothStatus status;
-
-	if (g_str_equal (property, "Connected") != FALSE) {
-		status = g_value_get_boolean (value) ?
-			BLUETOOTH_STATUS_CONNECTED :
-			BLUETOOTH_STATUS_DISCONNECTED;
-	} else if (g_str_equal (property, "State") != FALSE) {
-		GEnumClass *eclass;
-		GEnumValue *ev;
-		eclass = g_type_class_ref (BLUETOOTH_TYPE_STATUS);
-		ev = g_enum_get_value_by_nick (eclass, g_value_get_string (value));
-		if (ev == NULL) {
-			g_warning ("Unknown status '%s'", g_value_get_string (value));
-			status = BLUETOOTH_STATUS_DISCONNECTED;
-		} else {
-			status = ev->value;
-		}
-		g_type_class_unref (eclass);
-	} else
-		return;
-
-	path = dbus_g_proxy_get_path (iface);
-	if (get_iter_from_path (priv->store, &iter, path) == FALSE)
-		return;
-
-	gtk_tree_model_get(GTK_TREE_MODEL (priv->store), &iter,
-			   BLUETOOTH_COLUMN_SERVICES, &table,
-			   -1);
-
-	g_hash_table_insert (table,
-			     (gpointer) dbus_g_proxy_get_interface (iface),
-			     GINT_TO_POINTER (status));
-
-	tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
-	gtk_tree_model_row_changed (GTK_TREE_MODEL (priv->store), tree_path, &iter);
-	gtk_tree_path_free (tree_path);
-}
-
-static GHashTable *
-device_list_nodes (DBusGProxy *device, BluetoothClient *client, gboolean connect_signal)
+static char **
+device_list_uuids (GVariant *variant)
 {
-	GHashTable *table;
+	GPtrArray *ret;
+	const char **uuids;
 	guint i;
 
-	if (device == NULL)
+	if (variant == NULL)
 		return NULL;
 
-	table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
-
-	for (i = 0; i < G_N_ELEMENTS (detectable_interfaces); i++) {
-		DBusGProxy *iface;
-		GHashTable *props;
+	uuids = g_variant_get_strv (variant, NULL);
+	if (uuids == NULL)
+		return NULL;
 
-		/* Don't add the input interface for devices that already have
-		 * audio stuff */
-		if (g_str_equal (detectable_interfaces[i], BLUEZ_INPUT_INTERFACE)
-		    && g_hash_table_size (table) > 0)
-			continue;
+	ret = g_ptr_array_new ();
 
-		/* Don't add the audio interface if there's no Headset or AudioSink,
-		 * that means that it could only receive audio */
-		if (g_str_equal (detectable_interfaces[i], BLUEZ_AUDIO_INTERFACE)) {
-			if (g_hash_table_lookup (table, BLUEZ_HEADSET_INTERFACE) == NULL &&
-			    g_hash_table_lookup (table, BLUEZ_AUDIOSINK_INTERFACE) == NULL) {
-				continue;
-			}
-		}
+	for (i = 0; uuids[i] != NULL; i++) {
+		const char *uuid;
 
-		/* And skip interface if it's already in the hash table */
-		if (g_hash_table_lookup (table, detectable_interfaces[i]) != NULL)
+		uuid = bluetooth_uuid_to_string (uuids[i]);
+		if (uuid == NULL)
 			continue;
-
-		iface = dbus_g_proxy_new_from_proxy (device, detectable_interfaces[i], NULL);
-		if (dbus_g_proxy_call (iface, "GetProperties", NULL,
-				       G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &props,
-				       G_TYPE_INVALID) != FALSE) {
-			GValue *value;
-			BluetoothStatus status;
-
-			value = g_hash_table_lookup(props, "Connected");
-			if (value != NULL) {
-				status = g_value_get_boolean(value) ?
-					BLUETOOTH_STATUS_CONNECTED :
-					BLUETOOTH_STATUS_DISCONNECTED;
-			} else {
-				GEnumClass *eclass;
-				GEnumValue *ev;
-
-				eclass = g_type_class_ref (BLUETOOTH_TYPE_STATUS);
-				value = g_hash_table_lookup(props, "State");
-				ev = g_enum_get_value_by_nick (eclass, g_value_get_string (value));
-				if (ev == NULL) {
-					g_warning ("Unknown status '%s'", g_value_get_string (value));
-					status = BLUETOOTH_STATUS_DISCONNECTED;
-				} else {
-					status = ev->value;
-				}
-				g_type_class_unref (eclass);
-			}
-
-			g_hash_table_insert (table, (gpointer) detectable_interfaces[i], GINT_TO_POINTER (status));
-
-			if (connect_signal != FALSE) {
-				dbus_g_proxy_add_signal(iface, "PropertyChanged",
-							G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
-				dbus_g_proxy_connect_signal(iface, "PropertyChanged",
-							    G_CALLBACK(device_services_changed), client, NULL);
-			}
-		}
+		g_ptr_array_add (ret, g_strdup (uuid));
 	}
+	g_free (uuids);
 
-	if (g_hash_table_size (table) == 0) {
-		g_hash_table_destroy (table);
+	if (ret->len == 0) {
+		g_ptr_array_free (ret, TRUE);
 		return NULL;
 	}
 
-	return table;
-}
-
-static const char *
-uuid16_custom_to_string (guint uuid16, const char *uuid)
-{
-	switch (uuid16) {
-	case 0x2:
-		return "SyncMLClient";
-	case 0x5601:
-		return "Nokia SyncML Server";
-	default:
-		g_debug ("Unhandled custom UUID %s (0x%x)", uuid, uuid16);
-		return NULL;
-	}
-}
+	g_ptr_array_add (ret, NULL);
 
-/* Short names from Table 2 at:
- * https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm */
-static const char *
-uuid16_to_string (guint uuid16, const char *uuid)
-{
-	switch (uuid16) {
-	case 0x1101:
-		return "SerialPort";
-	case 0x1103:
-		return "DialupNetworking";
-	case 0x1104:
-		return "IrMCSync";
-	case 0x1105:
-		return "OBEXObjectPush";
-	case 0x1106:
-		return "OBEXFileTransfer";
-	case 0x1108:
-		return "HSP";
-	case 0x110A:
-		return "AudioSource";
-	case 0x110B:
-		return "AudioSink";
-	case 0x110c:
-		return "A/V_RemoteControlTarget";
-	case 0x110e:
-		return "A/V_RemoteControl";
-	case 0x1112:
-		return "Headset_-_AG";
-	case 0x1115:
-		return "PANU";
-	case 0x1116:
-		return "NAP";
-	case 0x1117:
-		return "GN";
-	case 0x111e:
-		return "Handsfree";
-	case 0x111F:
-		return "HandsfreeAudioGateway";
-	case 0x1124:
-		return "HumanInterfaceDeviceService";
-	case 0x112d:
-		return "SIM_Access";
-	case 0x112F:
-		return "Phonebook_Access_-_PSE";
-	case 0x1203:
-		return "GenericAudio";
-	case 0x1000: /* ServiceDiscoveryServerServiceClassID */
-	case 0x1200: /* PnPInformation */
-		/* Those are ignored */
-		return NULL;
-	case 0x1201:
-		return "GenericNetworking";
-	case 0x1303:
-		return "VideoSource";
-	case 0x8e771303:
-	case 0x8e771301:
-		return "SEMC HLA";
-	case 0x8e771401:
-		return "SEMC Watch Phone";
-	default:
-		g_debug ("Unhandled UUID %s (0x%x)", uuid, uuid16);
-		return NULL;
-	}
+	return (char **) g_ptr_array_free (ret, FALSE);
 }
 
-/**
- * bluetooth_uuid_to_string:
- * @uuid: a string representing a Bluetooth UUID
- *
- * Returns a string representing a human-readable (but not usable for display to users) version of the @uuid. Do not free the return value.
- *
- * Return value: a string.
- **/
-const char *
-bluetooth_uuid_to_string (const char *uuid)
+gboolean
+bluetooth_client_get_connectable(const char **uuids)
 {
-	char **parts;
-	guint uuid16;
-	gboolean is_custom = FALSE;
-
-	if (g_str_has_suffix (uuid, "-0000-1000-8000-0002ee000002") != FALSE)
-		is_custom = TRUE;
+	int i, j;
 
-	parts = g_strsplit (uuid, "-", -1);
-	if (parts == NULL || parts[0] == NULL) {
-		g_strfreev (parts);
-		return NULL;
+	for (i = 0; uuids && uuids[i] != NULL; i++) {
+		for (j = 0; j < G_N_ELEMENTS (connectable_uuids); j++) {
+			if (g_str_equal (connectable_uuids[j], uuids[i]))
+				return TRUE;
+		}
 	}
 
-	uuid16 = g_ascii_strtoull (parts[0], NULL, 16);
-	g_strfreev (parts);
-	if (uuid16 == 0)
-		return NULL;
-
-	if (is_custom == FALSE)
-		return uuid16_to_string (uuid16, uuid);
-	return uuid16_custom_to_string (uuid16, uuid);
+	return FALSE;
 }
 
-static char **
-device_list_uuids (GValue *value)
+static const char *
+phone_oui_to_icon_name (const char *bdaddr)
 {
-	GPtrArray *ret;
-	char **uuids;
-	guint i;
-
-	if (value == NULL)
-		return NULL;
+	char *vendor;
+	const char *ret = NULL;
 
-	uuids = g_value_get_boxed (value);
-	if (uuids == NULL)
+	vendor = oui_to_vendor (bdaddr);
+	if (vendor == NULL)
 		return NULL;
 
-	ret = g_ptr_array_new ();
+	if (strstr (vendor, "Apple") != NULL)
+		ret = "phone-apple-iphone";
+	else if (strstr (vendor, "Samsung") != NULL)
+		ret = "phone-samsung-galaxy-s";
+	else if (strstr (vendor, "Google") != NULL)
+		ret = "phone-google-nexus-one";
+	g_free (vendor);
 
-	for (i = 0; uuids[i] != NULL; i++) {
-		const char *uuid;
+	return ret;
+}
 
-		uuid = bluetooth_uuid_to_string (uuids[i]);
-		if (uuid == NULL)
-			continue;
-		g_ptr_array_add (ret, g_strdup (uuid));
-	}
-	if (ret->len == 0) {
-		g_ptr_array_free (ret, TRUE);
+static const char *
+icon_override (const char    *bdaddr,
+	       BluetoothType  type)
+{
+	/* audio-card, you're ugly */
+	switch (type) {
+	case BLUETOOTH_TYPE_HEADSET:
+		return "audio-headset";
+	case BLUETOOTH_TYPE_HEADPHONES:
+		return "audio-headphones";
+	case BLUETOOTH_TYPE_OTHER_AUDIO:
+		return "audio-speakers";
+	case BLUETOOTH_TYPE_PHONE:
+		return phone_oui_to_icon_name (bdaddr);
+	case BLUETOOTH_TYPE_DISPLAY:
+		return "video-display";
+	case BLUETOOTH_TYPE_SCANNER:
+		return "scanner";
+	case BLUETOOTH_TYPE_REMOTE_CONTROL:
+	case BLUETOOTH_TYPE_WEARABLE:
+	case BLUETOOTH_TYPE_TOY:
+		/* FIXME */
+	default:
 		return NULL;
 	}
-
-	g_ptr_array_add (ret, NULL);
-
-	return (char **) g_ptr_array_free (ret, FALSE);
 }
 
-static void device_changed(DBusGProxy *device, const char *property,
-					GValue *value, gpointer user_data)
+static void
+device_g_properties_changed (GDBusProxy      *device,
+			     GVariant        *changed_p,
+			     GStrv            invalidated_p,
+			     BluetoothClient *client)
 {
-	BluetoothClient *client = BLUETOOTH_CLIENT(user_data);
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	GVariantIter i;
+	const char *property;
 	GtkTreeIter iter;
+	GVariant *v;
 
-	DBG("client %p property %s", client, property);
-
-	if (get_iter_from_proxy(priv->store, &iter, device) == FALSE)
+	if (get_iter_from_proxy (priv->store, &iter, device) == FALSE)
 		return;
 
-	if (g_str_equal(property, "Name") == TRUE) {
-		const gchar *name = g_value_get_string(value);
-
-		gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_NAME, name, -1);
-	} else if (g_str_equal(property, "Alias") == TRUE) {
-		const gchar *alias = g_value_get_string(value);
-
-		gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_ALIAS, alias, -1);
-	} else if (g_str_equal(property, "Icon") == TRUE) {
-		const gchar *icon = g_value_get_string(value);
+	g_variant_iter_init (&i, changed_p);
+	while (g_variant_iter_next (&i, "{&sv}", &property, &v)) {
 
-		gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_ICON, icon, -1);
-	} else if (g_str_equal(property, "Paired") == TRUE) {
-		gboolean paired = g_value_get_boolean(value);
+		if (g_str_equal (property, "Name") == TRUE) {
+			const gchar *name = g_variant_get_string (v, NULL);
 
-		gtk_tree_store_set(priv->store, &iter,
-				BLUETOOTH_COLUMN_PAIRED, paired, -1);
-	} else if (g_str_equal(property, "Trusted") == TRUE) {
-		gboolean trusted = g_value_get_boolean(value);
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_NAME, name, -1);
+		} else if (g_str_equal (property, "Alias") == TRUE) {
+			const gchar *alias = g_variant_get_string (v, NULL);
 
-		gtk_tree_store_set(priv->store, &iter,
-				BLUETOOTH_COLUMN_TRUSTED, trusted, -1);
-	} else if (g_str_equal(property, "Connected") == TRUE) {
-		gboolean connected = g_value_get_boolean(value);
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_ALIAS, alias, -1);
+		} else if (g_str_equal (property, "Icon") == TRUE) {
+			const gchar *icon = g_variant_get_string (v, NULL);
 
-		gtk_tree_store_set(priv->store, &iter,
-				BLUETOOTH_COLUMN_CONNECTED, connected, -1);
-	} else if (g_str_equal (property, "UUIDs") == TRUE) {
-		GHashTable *services;
-		char **uuids;
+			/* See "Class" handling below */
+			if (g_strcmp0 (icon, "audio-card") != 0) {
+				gtk_tree_store_set (priv->store, &iter,
+						    BLUETOOTH_COLUMN_ICON, icon, -1);
+			}
+		} else if (g_str_equal (property, "Paired") == TRUE) {
+			gboolean paired = g_variant_get_boolean (v);
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_PAIRED, paired, -1);
+		} else if (g_str_equal (property, "Trusted") == TRUE) {
+			gboolean trusted = g_variant_get_boolean (v);
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_TRUSTED, trusted, -1);
+		} else if (g_str_equal (property, "Connected") == TRUE) {
+			gboolean connected = g_variant_get_boolean (v);
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_CONNECTED, connected, -1);
+		} else if (g_str_equal (property, "UUIDs") == TRUE) {
+			char **uuids;
+
+			uuids = device_list_uuids (v);
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_UUIDS, uuids, -1);
+			g_strfreev (uuids);
+		} else if (g_str_equal (property, "LegacyPairing") == TRUE) {
+			gboolean legacypairing;
+
+			legacypairing = g_variant_get_boolean (v);
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_LEGACYPAIRING, legacypairing,
+					    -1);
+		} else if (g_str_equal (property, "Class") == TRUE) {
+			BluetoothType type;
+			const char *icon = NULL;
+			char *bdaddr;
+
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+					    BLUETOOTH_COLUMN_ADDRESS, &bdaddr,
+					    -1);
+
+			type = v ? bluetooth_class_to_type (g_variant_get_uint32 (v)) : BLUETOOTH_TYPE_ANY;
+			icon = icon_override (bdaddr, type);
+
+			g_free (bdaddr);
+
+			if (icon) {
+				gtk_tree_store_set (priv->store, &iter,
+						    BLUETOOTH_COLUMN_TYPE, type,
+						    BLUETOOTH_COLUMN_ICON, icon,
+						    -1);
+			} else {
+				gtk_tree_store_set (priv->store, &iter,
+						    BLUETOOTH_COLUMN_TYPE, type,
+						    -1);
+			}
+		} else {
+			g_debug ("Unhandled property: %s", property);
+		}
 
-		services = device_list_nodes (device, client, TRUE);
-		uuids = device_list_uuids (value);
-		gtk_tree_store_set(priv->store, &iter,
-				   BLUETOOTH_COLUMN_SERVICES, services,
-				   BLUETOOTH_COLUMN_UUIDS, uuids, -1);
-		if (services != NULL)
-			g_hash_table_unref (services);
-		g_strfreev (uuids);
+		g_variant_unref (v);
 	}
 }
 
-static void add_device(DBusGProxy *adapter, GtkTreeIter *parent,
-					BluetoothClient *client,
-					const char *path, GHashTable *hash)
+static void
+device_added (ObjectManager   *manager,
+	      BluetoothClient *client,
+	      const char      *path,
+	      GVariant        *variant)
 {
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	DBusGProxy *device;
-	GValue *value;
-	const gchar *address, *alias, *name, *icon;
+	GDBusProxy *adapter;
+	Device1 *device;
+	Properties *properties;
+	GVariant *v, *dict;
+	const char *adapter_path, *address, *alias, *name, *icon;
 	char **uuids;
-	GHashTable *services;
 	gboolean paired, trusted, connected;
 	int legacypairing;
-	guint type;
-	GtkTreeIter iter;
-	gboolean cont;
+	BluetoothType type;
+	GtkTreeIter iter, parent;
+
+	device = device1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+						 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+						 BLUEZ_SERVICE,
+						 path,
+						 NULL,
+						 NULL);
+	if (device == NULL)
+		return;
 
-	services = NULL;
+	properties = properties_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+							G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+							BLUEZ_SERVICE,
+							path,
+							NULL,
+							NULL);
 
-	if (hash == NULL) {
-		device = dbus_g_proxy_new_from_proxy(adapter,
-						BLUEZ_DEVICE_INTERFACE, path);
+	dict = g_variant_lookup_value (variant, BLUEZ_DEVICE_INTERFACE,
+				       G_VARIANT_TYPE_DICTIONARY);
 
-		if (device != NULL)
-			device_get_properties(device, &hash, NULL);
-	} else
-		device = NULL;
+	v = g_variant_lookup_value (dict, "Adapter", G_VARIANT_TYPE_OBJECT_PATH);
+	adapter_path = v ? g_variant_get_string (v, NULL) : NULL;
+
+	v = g_variant_lookup_value (dict, "Address", G_VARIANT_TYPE_STRING);
+	address = v ? g_variant_get_string (v, NULL) : NULL;
 
-	if (hash != NULL) {
-		value = g_hash_table_lookup(hash, "Address");
-		address = value ? g_value_get_string(value) : NULL;
+	v = g_variant_lookup_value (dict, "Alias", G_VARIANT_TYPE_STRING);
+	alias = v ? g_variant_get_string (v, NULL) : NULL;
 
-		value = g_hash_table_lookup(hash, "Alias");
-		alias = value ? g_value_get_string(value) : NULL;
+	v = g_variant_lookup_value (dict, "Name", G_VARIANT_TYPE_STRING);
+	name = v ? g_variant_get_string (v, NULL) : NULL;
 
-		value = g_hash_table_lookup(hash, "Name");
-		name = value ? g_value_get_string(value) : NULL;
+	v = g_variant_lookup_value (dict, "Class", G_VARIANT_TYPE_UINT32);
+	type = v ? bluetooth_class_to_type (g_variant_get_uint32 (v)) : BLUETOOTH_TYPE_ANY;
+	icon = icon_override (address, type);
 
-		value = g_hash_table_lookup(hash, "Class");
-		type = value ? bluetooth_class_to_type(g_value_get_uint(value)) : BLUETOOTH_TYPE_ANY;
+	if (icon == NULL) {
+		v = g_variant_lookup_value (dict, "Icon", G_VARIANT_TYPE_STRING);
+		icon = v ? g_variant_get_string (v, NULL) : "bluetooth";
+	}
 
-		value = g_hash_table_lookup(hash, "Icon");
-		icon = value ? g_value_get_string(value) : "bluetooth";
+	v = g_variant_lookup_value (dict, "Paired", G_VARIANT_TYPE_BOOLEAN);
+	paired = v ? g_variant_get_boolean (v) : FALSE;
 
-		value = g_hash_table_lookup(hash, "Paired");
-		paired = value ? g_value_get_boolean(value) : FALSE;
+	v = g_variant_lookup_value (dict, "Trusted", G_VARIANT_TYPE_BOOLEAN);
+	trusted = v ? g_variant_get_boolean (v) : FALSE;
 
-		value = g_hash_table_lookup(hash, "Trusted");
-		trusted = value ? g_value_get_boolean(value) : FALSE;
+	v = g_variant_lookup_value (dict, "Connected", G_VARIANT_TYPE_BOOLEAN);
+	connected = v ? g_variant_get_boolean (v) : FALSE;
 
-		value = g_hash_table_lookup(hash, "Connected");
-		connected = value ? g_value_get_boolean(value) : FALSE;
+	v = g_variant_lookup_value (dict, "UUIDs", G_VARIANT_TYPE_STRING_ARRAY);
+	uuids = device_list_uuids (v);
 
-		value = g_hash_table_lookup(hash, "UUIDs");
-		uuids = device_list_uuids (value);
+	v = g_variant_lookup_value (dict, "LegacyPairing", G_VARIANT_TYPE_BOOLEAN);
+	legacypairing = v ? g_variant_get_boolean (v) : -1;
 
-		value = g_hash_table_lookup(hash, "LegacyPairing");
-		legacypairing = value ? g_value_get_boolean(value) : -1;
-	} else {
-		if (device)
-			g_object_unref (device);
+	if (get_iter_from_path (priv->store, &parent, adapter_path) == FALSE) {
+		g_object_unref (device);
 		return;
 	}
 
-	cont = gtk_tree_model_iter_children(GTK_TREE_MODEL(priv->store),
-								&iter, parent);
-
-	while (cont == TRUE) {
-		gchar *value;
-
-		gtk_tree_model_get(GTK_TREE_MODEL(priv->store), &iter,
-					BLUETOOTH_COLUMN_ADDRESS, &value, -1);
-
-		if (g_ascii_strcasecmp(address, value) == 0) {
-			gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_ADDRESS, address,
-					BLUETOOTH_COLUMN_ALIAS, alias,
-					BLUETOOTH_COLUMN_NAME, name,
-					BLUETOOTH_COLUMN_TYPE, type,
-					BLUETOOTH_COLUMN_ICON, icon,
-					BLUETOOTH_COLUMN_LEGACYPAIRING, legacypairing,
-					-1);
-			if (uuids != NULL) {
-				gtk_tree_store_set(priv->store, &iter,
+	gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &parent,
+			    BLUETOOTH_COLUMN_PROXY, &adapter, -1);
+
+	if (get_iter_from_address (priv->store, &iter, address, adapter) == FALSE) {
+		gtk_tree_store_insert_with_values (priv->store, &iter, &parent, -1,
+						   BLUETOOTH_COLUMN_ADDRESS, address,
+						   BLUETOOTH_COLUMN_ALIAS, alias,
+						   BLUETOOTH_COLUMN_NAME, name,
+						   BLUETOOTH_COLUMN_TYPE, type,
+						   BLUETOOTH_COLUMN_ICON, icon,
+						   BLUETOOTH_COLUMN_LEGACYPAIRING, legacypairing,
 						   BLUETOOTH_COLUMN_UUIDS, uuids,
+						   BLUETOOTH_COLUMN_PAIRED, paired,
+						   BLUETOOTH_COLUMN_CONNECTED, connected,
+						   BLUETOOTH_COLUMN_TRUSTED, trusted,
+						   BLUETOOTH_COLUMN_PROXY, device,
+						   BLUETOOTH_COLUMN_PROPERTIES, properties,
 						   -1);
-			}
-
-			if (device != NULL) {
-				services = device_list_nodes (device, client, FALSE);
-
-				gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_PROXY, device,
-					BLUETOOTH_COLUMN_CONNECTED, connected,
-					BLUETOOTH_COLUMN_TRUSTED, trusted,
-					BLUETOOTH_COLUMN_PAIRED, paired,
-					BLUETOOTH_COLUMN_SERVICES, services,
-					-1);
-			}
-
-			goto done;
-		}
-		g_free (value);
-
-		cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(priv->store), &iter);
-	}
-
-	services = device_list_nodes (device, client, TRUE);
-
-	gtk_tree_store_insert_with_values(priv->store, &iter, parent, -1,
-				BLUETOOTH_COLUMN_PROXY, device,
-				BLUETOOTH_COLUMN_ADDRESS, address,
-				BLUETOOTH_COLUMN_ALIAS, alias,
-				BLUETOOTH_COLUMN_NAME, name,
-				BLUETOOTH_COLUMN_TYPE, type,
-				BLUETOOTH_COLUMN_ICON, icon,
-				BLUETOOTH_COLUMN_PAIRED, paired,
-				BLUETOOTH_COLUMN_TRUSTED, trusted,
-				BLUETOOTH_COLUMN_CONNECTED, connected,
-				BLUETOOTH_COLUMN_SERVICES, services,
-				BLUETOOTH_COLUMN_UUIDS, uuids,
-				BLUETOOTH_COLUMN_LEGACYPAIRING, legacypairing,
-				-1);
-
-done:
-	if (device != NULL) {
-		dbus_g_proxy_add_signal(device, "PropertyChanged",
-				G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
-		dbus_g_proxy_connect_signal(device, "PropertyChanged",
-				G_CALLBACK(device_changed), client, NULL);
-		g_object_unref(device);
+	} else {
+		gtk_tree_store_set(priv->store, &iter,
+				   BLUETOOTH_COLUMN_ADDRESS, address,
+				   BLUETOOTH_COLUMN_ALIAS, alias,
+				   BLUETOOTH_COLUMN_NAME, name,
+				   BLUETOOTH_COLUMN_TYPE, type,
+				   BLUETOOTH_COLUMN_ICON, icon,
+				   BLUETOOTH_COLUMN_LEGACYPAIRING, legacypairing,
+				   BLUETOOTH_COLUMN_UUIDS, uuids,
+				   BLUETOOTH_COLUMN_PAIRED, paired,
+				   BLUETOOTH_COLUMN_CONNECTED, connected,
+				   BLUETOOTH_COLUMN_TRUSTED, trusted,
+				   BLUETOOTH_COLUMN_PROXY, device,
+				   BLUETOOTH_COLUMN_PROPERTIES, properties,
+				   -1);
 	}
 	g_strfreev (uuids);
-	if (services)
-		g_hash_table_unref (services);
+
+	g_signal_connect (G_OBJECT (device), "g-properties-changed",
+			  G_CALLBACK (device_g_properties_changed), client);
+
+	g_object_unref (properties);
+	g_object_unref (device);
+	g_object_unref (adapter);
 }
 
-static void device_found(DBusGProxy *adapter, const char *address,
-					GHashTable *hash, gpointer user_data)
+static void
+device_removed (const char      *path,
+		BluetoothClient *client)
 {
-	BluetoothClient *client = user_data;
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 	GtkTreeIter iter;
 
-	DBG("client %p address %s", client, address);
-
-	if (get_iter_from_proxy(priv->store, &iter, adapter) == TRUE)
-		add_device(adapter, &iter, client, NULL, hash);
+	if (get_iter_from_path(priv->store, &iter, path) == TRUE) {
+		g_signal_emit (G_OBJECT (client), signals[DEVICE_REMOVED], 0, path);
+		gtk_tree_store_remove(priv->store, &iter);
+	}
 }
 
-static void device_created(DBusGProxy *adapter,
-				const char *path, gpointer user_data)
+static void
+powered_callback (GDBusProxy   *proxy,
+		  GAsyncResult *res,
+		  gpointer	data)
 {
-	BluetoothClient *client = user_data;
-	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	GtkTreeIter iter;
+	GError *error = NULL;
 
-	DBG("client %p path %s", client, path);
+	if (!properties_call_set_finish (PROPERTIES(proxy), res, &error)) {
+		g_debug ("Call to Set Powered failed %s: %s",
+			 g_dbus_proxy_get_object_path (proxy), error->message);
+		g_error_free (error);
+	}
 
-	if (get_iter_from_proxy(priv->store, &iter, adapter) == TRUE)
-		add_device(adapter, &iter, client, path, NULL);
+	g_object_unref (proxy);
 }
 
-static void device_removed(DBusGProxy *adapter,
-				const char *path, gpointer user_data)
+static gboolean
+adapter_set_powered (BluetoothClient *client,
+		     const char *path,
+		     gboolean powered)
 {
-	BluetoothClient *client = user_data;
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	Properties *properties;
 	GtkTreeIter iter;
 
-	DBG("client %p path %s", client, path);
+	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
 
-	if (get_iter_from_path(priv->store, &iter, path) == TRUE)
-		gtk_tree_store_remove(priv->store, &iter);
+	if (get_iter_from_path (priv->store, &iter, path) == FALSE)
+		return FALSE;
+
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+			    BLUETOOTH_COLUMN_PROPERTIES, &properties, -1);
+
+	if (properties == NULL)
+		return FALSE;
+
+
+	properties_call_set (properties,
+			     BLUEZ_ADAPTER_INTERFACE,
+			     "Powered",
+			     g_variant_new_variant (g_variant_new_boolean (powered)),
+			     NULL,
+			     (GAsyncReadyCallback) powered_callback,
+			     NULL);
+
+	return TRUE;
 }
 
-static void adapter_changed(DBusGProxy *adapter, const char *property,
-					GValue *value, gpointer user_data)
+static void
+default_adapter_changed (ObjectManager   *manager,
+			 const char      *path,
+			 BluetoothClient *client)
 {
-	BluetoothClient *client = BLUETOOTH_CLIENT(user_data);
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 	GtkTreeIter iter;
-	gboolean notify = FALSE;
+	GtkTreePath *tree_path;
+	gboolean powered;
 
-	DBG("client %p property %s", client, property);
+	g_assert (!priv->default_adapter);
 
-	if (get_iter_from_proxy(priv->store, &iter, adapter) == FALSE)
+	if (get_iter_from_path (priv->store, &iter, path) == FALSE)
 		return;
 
-	if (g_str_equal(property, "Name") == TRUE) {
-		const gchar *name = g_value_get_string(value);
-
-		gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_NAME, name, -1);
-	} else if (g_str_equal(property, "Discovering") == TRUE) {
-		gboolean discovering = g_value_get_boolean(value);
+	tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
+	priv->default_adapter = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->store), tree_path);
+	gtk_tree_path_free (tree_path);
 
-		gtk_tree_store_set(priv->store, &iter,
-				BLUETOOTH_COLUMN_DISCOVERING, discovering, -1);
-		notify = TRUE;
-	} else if (g_str_equal(property, "Powered") == TRUE) {
-		gboolean powered = g_value_get_boolean(value);
-		gboolean is_default;
+	gtk_tree_store_set (priv->store, &iter,
+			    BLUETOOTH_COLUMN_DEFAULT, TRUE, -1);
 
-		gtk_tree_store_set(priv->store, &iter,
-				   BLUETOOTH_COLUMN_POWERED, powered, -1);
-		gtk_tree_model_get(GTK_TREE_MODEL(priv->store), &iter,
-				   BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
-		if (is_default != FALSE && powered != priv->default_adapter_powered) {
-			priv->default_adapter_powered = powered;
-			g_object_notify (G_OBJECT (client), "default-adapter-powered");
-		}
-	} else if (g_str_equal(property, "Discoverable") == TRUE) {
-		gboolean discoverable = g_value_get_boolean(value);
+	gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+			   BLUETOOTH_COLUMN_POWERED, &powered, -1);
 
-		gtk_tree_store_set(priv->store, &iter,
-				BLUETOOTH_COLUMN_DISCOVERABLE, discoverable, -1);
-		notify = TRUE;
+	if (powered) {
+		g_object_notify (G_OBJECT (client), "default-adapter");
+		g_object_notify (G_OBJECT (client), "default-adapter-powered");
+		g_object_notify (G_OBJECT (client), "default-adapter-discoverable");
+		g_object_notify (G_OBJECT (client), "default-adapter-discovering");
+		g_object_notify (G_OBJECT (client), "default-adapter-name");
+		return;
 	}
 
-	if (notify != FALSE) {
-		GtkTreePath *path;
-
-		/* Tell the world */
-		path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
-		gtk_tree_model_row_changed (GTK_TREE_MODEL (priv->store), path, &iter);
-		gtk_tree_path_free (path);
-	}
+	/*
+	 * If the adapter is turn off (Powered = False in bluetooth) object
+	 * notifications will be sent only when a Powered = True signal arrives
+	 * from bluetoothd
+	 */
+	adapter_set_powered (client, path, TRUE);
 }
 
-static void adapter_added(DBusGProxy *manager,
-				const char *path, gpointer user_data)
+static void
+adapter_g_properties_changed (GDBusProxy      *adapter,
+			      GVariant        *changed_p,
+			      GStrv            invalidated_p,
+			      BluetoothClient *client)
 {
-	BluetoothClient *client = user_data;
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	GVariantIter i;
+	const char *property;
 	GtkTreeIter iter;
-	DBusGProxy *adapter;
-	GPtrArray *devices;
-	GHashTable *hash = NULL;
-	GValue *value;
-	const gchar *address, *name;
-	gboolean discovering, discoverable, powered;
+	GVariant *v;
+	gboolean notify = FALSE;
 
-	DBG("client %p path %s", client, path);
+	if (get_iter_from_proxy (priv->store, &iter, adapter) == FALSE)
+		return;
 
-	adapter = dbus_g_proxy_new_from_proxy(manager,
-					BLUEZ_ADAPTER_INTERFACE, path);
+	g_variant_iter_init (&i, changed_p);
+	while (g_variant_iter_next (&i, "{&sv}", &property, &v)) {
+		if (g_str_equal (property, "Name") == TRUE) {
+			const gchar *name = g_variant_get_string (v, NULL);
+			gboolean is_default;
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_NAME, name, -1);
+			gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+					    BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
+			if (is_default != FALSE) {
+				g_object_notify (G_OBJECT (client), "default-adapter-powered");
+				g_object_notify (G_OBJECT (client), "default-adapter-name");
+			}
+			notify = TRUE;
+		} else if (g_str_equal (property, "Discovering") == TRUE) {
+			gboolean discovering = g_variant_get_boolean (v);
+			gboolean is_default;
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_DISCOVERING, discovering, -1);
+			gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+					    BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
+			if (is_default != FALSE)
+				g_object_notify (G_OBJECT (client), "default-adapter-discovering");
+			notify = TRUE;
+		} else if (g_str_equal (property, "Powered") == TRUE) {
+			gboolean powered = g_variant_get_boolean (v);
+			gboolean is_default;
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_POWERED, powered, -1);
+			gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+					    BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
+			if (is_default != FALSE && powered) {
+				g_object_notify (G_OBJECT (client), "default-adapter");
+				g_object_notify (G_OBJECT (client), "default-adapter-powered");
+				g_object_notify (G_OBJECT (client), "default-adapter-discoverable");
+				g_object_notify (G_OBJECT (client), "default-adapter-discovering");
+				g_object_notify (G_OBJECT (client), "default-adapter-name");
+			}
+			notify = TRUE;
+		} else if (g_str_equal (property, "Discoverable") == TRUE) {
+			gboolean discoverable = g_variant_get_boolean (v);
+			gboolean is_default;
+
+			gtk_tree_store_set (priv->store, &iter,
+					    BLUETOOTH_COLUMN_DISCOVERABLE, discoverable, -1);
+			gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+					    BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
+			if (is_default != FALSE)
+				g_object_notify (G_OBJECT (client), "default-adapter-discoverable");
+			notify = TRUE;
+		}
 
-	adapter_get_properties(adapter, &hash, NULL);
-	if (hash != NULL) {
-		value = g_hash_table_lookup(hash, "Address");
-		address = value ? g_value_get_string(value) : NULL;
+		if (notify != FALSE) {
+			GtkTreePath *path;
 
-		value = g_hash_table_lookup(hash, "Name");
-		name = value ? g_value_get_string(value) : NULL;
+			/* Tell the world */
+			path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
+			gtk_tree_model_row_changed (GTK_TREE_MODEL (priv->store), path, &iter);
+			gtk_tree_path_free (path);
+		}
+		g_variant_unref (v);
+	}
+}
 
-		value = g_hash_table_lookup(hash, "Discovering");
-		discovering = value ? g_value_get_boolean(value) : FALSE;
+static void
+adapter_added (ObjectManager   *manager,
+	       const char      *path,
+	       GVariant        *variant,
+	       BluetoothClient *client)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	GtkTreeIter iter;
+	Adapter1 *adapter;
+	Properties *properties;
+	const gchar *address, *name;
+	GVariant *v, *dict;
+	gboolean discovering, discoverable, powered;
 
-		value = g_hash_table_lookup(hash, "Powered");
-		powered = value ? g_value_get_boolean(value) : FALSE;
+	adapter = adapter1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+						   G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+						   BLUEZ_SERVICE,
+						   path,
+						   NULL,
+						   NULL);
 
-		value = g_hash_table_lookup(hash, "Devices");
-		devices = value ? g_value_get_boxed (value) : NULL;
+	properties = properties_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+							G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+							BLUEZ_SERVICE,
+							path,
+							NULL,
+							NULL);
 
-		value = g_hash_table_lookup (hash, "Discoverable");
-		discoverable = value ? g_value_get_boolean (value) : FALSE;
-	} else {
-		address = NULL;
-		name = NULL;
-		discovering = FALSE;
-		discoverable = FALSE;
-		powered = FALSE;
-		devices = NULL;
-	}
+	dict = g_variant_lookup_value (variant, BLUEZ_ADAPTER_INTERFACE,
+                              G_VARIANT_TYPE_DICTIONARY);
+
+	v = g_variant_lookup_value (dict, "Address", G_VARIANT_TYPE_STRING);
+	address = v ? g_variant_get_string (v, NULL) : NULL;
+
+	v = g_variant_lookup_value (dict, "Name", G_VARIANT_TYPE_STRING);
+	name = v ? g_variant_get_string (v, NULL) : NULL;
+
+	v = g_variant_lookup_value (dict, "Discovering", G_VARIANT_TYPE_BOOLEAN);
+	discovering = v ? g_variant_get_boolean (v) : FALSE;
+
+	v = g_variant_lookup_value (dict, "Powered", G_VARIANT_TYPE_BOOLEAN);
+	powered = v ? g_variant_get_boolean (v) : FALSE;
+
+	v = g_variant_lookup_value (dict, "Discoverable", G_VARIANT_TYPE_BOOLEAN);
+	discoverable = v ? g_variant_get_boolean (v) : FALSE;
 
 	gtk_tree_store_insert_with_values(priv->store, &iter, NULL, -1,
 					  BLUETOOTH_COLUMN_PROXY, adapter,
+					  BLUETOOTH_COLUMN_PROPERTIES, properties,
 					  BLUETOOTH_COLUMN_ADDRESS, address,
 					  BLUETOOTH_COLUMN_NAME, name,
 					  BLUETOOTH_COLUMN_DISCOVERING, discovering,
@@ -982,218 +758,407 @@ static void adapter_added(DBusGProxy *manager,
 					  BLUETOOTH_COLUMN_POWERED, powered,
 					  -1);
 
-	dbus_g_proxy_add_signal(adapter, "PropertyChanged",
-				G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(adapter, "PropertyChanged",
-				G_CALLBACK(adapter_changed), client, NULL);
-
-	dbus_g_proxy_add_signal(adapter, "DeviceCreated",
-				DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(adapter, "DeviceCreated",
-				G_CALLBACK(device_created), client, NULL);
-
-	dbus_g_proxy_add_signal(adapter, "DeviceRemoved",
-				DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(adapter, "DeviceRemoved",
-				G_CALLBACK(device_removed), client, NULL);
-
-	dbus_g_proxy_add_signal(adapter, "DeviceFound",
-			G_TYPE_STRING, DBUS_TYPE_G_DICTIONARY, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(adapter, "DeviceFound",
-				G_CALLBACK(device_found), client, NULL);
-
-	if (devices != NULL) {
-		int i;
-
-		for (i = 0; i < devices->len; i++) {
-			gchar *path = g_ptr_array_index(devices, i);
-			device_created(adapter, path, client);
-			g_free(path);
-		}
-	}
+	g_signal_connect (G_OBJECT (adapter), "g-properties-changed",
+			  G_CALLBACK (adapter_g_properties_changed), client);
 
-	g_object_unref(adapter);
+	if (!priv->default_adapter)
+		default_adapter_changed (manager, path, client);
+
+	g_object_unref (properties);
+	g_object_unref (adapter);
 }
 
-static void adapter_removed(DBusGProxy *manager,
-				const char *path, gpointer user_data)
+static void
+adapter_removed (ObjectManager   *manager,
+		 const char      *path,
+		 BluetoothClient *client)
 {
-	BluetoothClient *client = user_data;
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 	GtkTreeIter iter;
-	gboolean cont;
+	gboolean was_default;
 
-	DBG("client %p path %s", client, path);
+	if (get_iter_from_path (priv->store, &iter, path) == FALSE)
+		return;
 
-	cont = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(priv->store),
-									&iter);
+	gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+			   BLUETOOTH_COLUMN_DEFAULT, &was_default, -1);
 
-	while (cont == TRUE) {
-		DBusGProxy *adapter;
-		const char *adapter_path;
-		gboolean found;
+	if (!was_default)
+		return;
 
-		gtk_tree_model_get(GTK_TREE_MODEL(priv->store), &iter,
-					BLUETOOTH_COLUMN_PROXY, &adapter, -1);
+	g_clear_pointer (&priv->default_adapter, gtk_tree_row_reference_free);
+	gtk_tree_store_remove (priv->store, &iter);
 
-		adapter_path = dbus_g_proxy_get_path(adapter);
+	if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(priv->store),
+					   &iter)) {
+		GDBusProxy *adapter;
+		const char *adapter_path;
 
-		found = g_str_equal(path, adapter_path);
-		if (found == TRUE) {
-			g_signal_handlers_disconnect_by_func(adapter,
-						adapter_changed, client);
-			g_signal_handlers_disconnect_by_func(adapter,
-						device_created, client);
-			g_signal_handlers_disconnect_by_func(adapter,
-						device_removed, client);
-			g_signal_handlers_disconnect_by_func(adapter,
-						device_found, client);
-		}
+		gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+				   BLUETOOTH_COLUMN_PROXY, &adapter, -1);
+
+		adapter_path = g_dbus_proxy_get_object_path (adapter);
+		default_adapter_changed (manager, adapter_path, client);
 
 		g_object_unref(adapter);
+	} else {
+		g_object_notify (G_OBJECT (client), "default-adapter");
+		g_object_notify (G_OBJECT (client), "default-adapter-powered");
+		g_object_notify (G_OBJECT (client), "default-adapter-discoverable");
+		g_object_notify (G_OBJECT (client), "default-adapter-discovering");
+	}
+}
 
-		if (found == TRUE) {
-			cont = gtk_tree_store_remove(priv->store, &iter);
-			continue;
-		}
+static void
+interface_added (BluetoothClient *client,
+		 const char *path,
+		 GVariant   *variant)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 
-		cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(priv->store),
-									&iter);
+	if (g_variant_lookup_value (variant, BLUEZ_ADAPTER_INTERFACE,
+				    G_VARIANT_TYPE_DICTIONARY)) {
+		g_debug ("New Adapter interface added.");
+		adapter_added (priv->manager, path, variant, client);
+		return;
 	}
 
-	/* No adapters left in the tree? */
-	if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL(priv->store), NULL) == 0) {
-		g_free(priv->default_adapter);
-		priv->default_adapter = NULL;
-		priv->default_adapter_powered = FALSE;
-		g_object_notify (G_OBJECT (client), "default-adapter");
-		g_object_notify (G_OBJECT (client), "default-adapter-powered");
+	if (g_variant_lookup_value (variant, BLUEZ_DEVICE_INTERFACE,
+				    G_VARIANT_TYPE_DICTIONARY)) {
+		g_debug ("New Device interface added.");
+		device_added (priv->manager, client, path, variant);
+		return;
 	}
 }
 
-static void default_adapter_changed(DBusGProxy *manager,
-				const char *path, gpointer user_data)
+static void
+interface_removed (BluetoothClient *client,
+		   const char      *path,
+		   GVariant        *variant)
 {
-	BluetoothClient *client = user_data;
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	GtkTreeIter iter;
-	gboolean cont;
-
-	DBG("client %p path %s", client, path);
+	const char **ifaces;
+	int i;
 
-	cont = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(priv->store),
-									&iter);
+	ifaces = g_variant_get_strv (variant, NULL);
 
-	while (cont == TRUE) {
-		DBusGProxy *adapter;
-		const char *adapter_path;
-		gboolean found, powered;
+	for (i = 0 ; ifaces[i] != NULL ; i++) {
+		if (g_strcmp0(ifaces[i], BLUEZ_ADAPTER_INTERFACE) == 0) {
+			adapter_removed(priv->manager, path, client);
+			return;
+		}
 
-		gtk_tree_model_get(GTK_TREE_MODEL(priv->store), &iter,
-				   BLUETOOTH_COLUMN_PROXY, &adapter,
-				   BLUETOOTH_COLUMN_POWERED, &powered, -1);
+		if (g_strcmp0(ifaces[i], BLUEZ_DEVICE_INTERFACE) == 0) {
+			device_removed (path, client);
+			return;
+		}
+	}
+}
 
-		adapter_path = dbus_g_proxy_get_path(adapter);
+static void
+object_manager_g_signal (GDBusProxy      *proxy,
+			 gchar           *sender_name,
+			 gchar           *signal_name,
+			 GVariant        *parameters,
+			 BluetoothClient *client)
+{
+	char *object_path;
+	GVariant *variant;
 
-		found = g_str_equal(path, adapter_path);
+	g_variant_get (parameters, "(o*)", &object_path, &variant);
 
-		g_object_unref(adapter);
+	if (g_strcmp0 (signal_name, "InterfacesAdded") == 0) {
+		interface_added (client, object_path, variant);
+	} else if (g_strcmp0 (signal_name, "InterfacesRemoved") == 0) {
+		interface_removed (client, object_path, variant);
+	} else {
+		g_assert_not_reached ();
+	}
 
-		if (found != FALSE)
-			priv->default_adapter_powered = powered;
+	g_free (object_path);
+}
 
-		gtk_tree_store_set(priv->store, &iter,
-					BLUETOOTH_COLUMN_DEFAULT, found, -1);
+static void
+bluez_appeared_cb (GDBusConnection *connection,
+		   const gchar     *name,
+		   const gchar     *name_owner,
+		   BluetoothClient *client)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	GVariantIter iter;
+	GVariant *variant, *v, *ifaces;
+	char *key;
+
+	priv->manager = object_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+							       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+							       BLUEZ_SERVICE,
+							       BLUEZ_MANAGER_PATH,
+							       NULL,
+							       NULL);
+
+	g_signal_connect (G_OBJECT (priv->manager), "g-signal",
+			  G_CALLBACK (object_manager_g_signal), client);
+
+	variant = NULL;
+	object_manager_call_get_managed_objects_sync (OBJECT_MANAGER (priv->manager),
+						      &variant, NULL, NULL);
+	if (variant == NULL)
+		return;
 
-		cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(priv->store),
-									&iter);
+	g_variant_iter_init (&iter, variant);
+	while ((v = g_variant_iter_next_value (&iter))) {
+		g_variant_get (v, "{o*}", &key, &ifaces);
+		interface_added (client, key, ifaces);
 	}
 
-	/* Record the new default adapter */
-	g_free(priv->default_adapter);
-	priv->default_adapter = g_strdup(path);
-	g_object_notify (G_OBJECT (client), "default-adapter");
-	g_object_notify (G_OBJECT (client), "default-adapter-powered");
+	g_variant_unref (variant);
 }
 
-static void name_owner_changed(DBusGProxy *dbus, const char *name,
-			const char *prev, const char *new, gpointer user_data)
+static void
+bluez_vanished_cb (GDBusConnection *connection,
+		   const gchar     *name,
+		   BluetoothClient *client)
 {
-	BluetoothClient *client = user_data;
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	GtkTreeIter iter;
-	gboolean cont;
-
-	if (g_str_equal(name, BLUEZ_SERVICE) == FALSE || *new != '\0')
-		return;
 
-	DBG("client %p name %s", client, name);
+	g_clear_pointer (&priv->default_adapter, gtk_tree_row_reference_free);
 
-	cont = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(priv->store),
-									&iter);
+	gtk_tree_store_clear (priv->store);
 
-	while (cont == TRUE)
-		cont = gtk_tree_store_remove(priv->store, &iter);
+	g_clear_object (&priv->manager);
 }
 
 static void bluetooth_client_init(BluetoothClient *client)
 {
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	GPtrArray *array = NULL;
-	gchar *default_path = NULL;
-
-	DBG("client %p", client);
 
 	priv->store = gtk_tree_store_new(_BLUETOOTH_NUM_COLUMNS, G_TYPE_OBJECT,
-					 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+					 G_TYPE_OBJECT, G_TYPE_STRING,
+					 G_TYPE_STRING, G_TYPE_STRING,
 					 G_TYPE_UINT, G_TYPE_STRING,
 					 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
 					 G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT,
 					 G_TYPE_BOOLEAN, G_TYPE_HASH_TABLE, G_TYPE_STRV);
 
-	priv->dbus = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS,
-				DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
-
-	dbus_g_proxy_add_signal(priv->dbus, "NameOwnerChanged",
-					G_TYPE_STRING, G_TYPE_STRING,
-					G_TYPE_STRING, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(priv->dbus, "NameOwnerChanged",
-				G_CALLBACK(name_owner_changed), client, NULL);
-
-	priv->manager = dbus_g_proxy_new_for_name(connection, BLUEZ_SERVICE,
-				BLUEZ_MANAGER_PATH, BLUEZ_MANAGER_INTERFACE);
-
-	dbus_g_proxy_add_signal(priv->manager, "AdapterAdded",
-				DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(priv->manager, "AdapterAdded",
-				G_CALLBACK(adapter_added), client, NULL);
-
-	dbus_g_proxy_add_signal(priv->manager, "AdapterRemoved",
-				DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(priv->manager, "AdapterRemoved",
-				G_CALLBACK(adapter_removed), client, NULL);
-
-	dbus_g_proxy_add_signal(priv->manager, "DefaultAdapterChanged",
-				DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
-	dbus_g_proxy_connect_signal(priv->manager, "DefaultAdapterChanged",
-			G_CALLBACK(default_adapter_changed), client, NULL);
-
-	manager_list_adapters(priv->manager, &array, NULL);
-	if (array != NULL) {
-		int i;
-
-		for (i = 0; i < array->len; i++) {
-			gchar *path = g_ptr_array_index(array, i);
-			adapter_added(priv->manager, path, client);
-			g_free(path);
+	priv->owner_change_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+						  BLUEZ_SERVICE,
+						  G_BUS_NAME_WATCHER_FLAGS_NONE,
+						  (GBusNameAppearedCallback) bluez_appeared_cb,
+						  (GBusNameVanishedCallback) bluez_vanished_cb,
+						  client, NULL);
+}
+
+static GDBusProxy *
+_bluetooth_client_get_default_adapter(BluetoothClient *client)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	GDBusProxy *adapter;
+
+	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), NULL);
+
+	if (priv->default_adapter == NULL)
+		return NULL;
+
+	path = gtk_tree_row_reference_get_path (priv->default_adapter);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+			    BLUETOOTH_COLUMN_PROXY, &adapter, -1);
+	gtk_tree_path_free (path);
+
+	return adapter;
+}
+
+static const char*
+_bluetooth_client_get_default_adapter_path (BluetoothClient *self)
+{
+	GDBusProxy *adapter = _bluetooth_client_get_default_adapter (self);
+
+	if (adapter != NULL) {
+		const char *ret = g_dbus_proxy_get_object_path (adapter);
+		g_object_unref (adapter);
+		return ret;
+	}
+	return NULL;
+}
+
+static gboolean
+_bluetooth_client_get_default_adapter_powered (BluetoothClient *self)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE (self);
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gboolean ret;
+
+	if (priv->default_adapter == NULL)
+		return FALSE;
+
+	path = gtk_tree_row_reference_get_path (priv->default_adapter);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter, BLUETOOTH_COLUMN_POWERED, &ret, -1);
+	gtk_tree_path_free (path);
+
+	return ret;
+}
+
+static char *
+_bluetooth_client_get_default_adapter_name (BluetoothClient *self)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE (self);
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	char *ret;
+
+	if (priv->default_adapter == NULL)
+		return NULL;
+
+	path = gtk_tree_row_reference_get_path (priv->default_adapter);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter, BLUETOOTH_COLUMN_NAME, &ret, -1);
+	gtk_tree_path_free (path);
+
+	return ret;
+}
+
+/**
+ * _bluetooth_client_get_discoverable:
+ * @client: a #BluetoothClient
+ *
+ * Gets the default adapter's discoverable status, cached in the adapter model.
+ *
+ * Returns: the discoverable status, or FALSE if no default adapter exists
+ */
+static gboolean
+_bluetooth_client_get_discoverable (BluetoothClient *client)
+{
+	BluetoothClientPrivate *priv;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gboolean ret;
+
+	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
+
+	priv = BLUETOOTH_CLIENT_GET_PRIVATE (client);
+	if (priv->default_adapter == NULL)
+		return FALSE;
+
+	path = gtk_tree_row_reference_get_path (priv->default_adapter);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+                            BLUETOOTH_COLUMN_DISCOVERABLE, &ret, -1);
+
+	return ret;
+}
+
+/**
+ * _bluetooth_client_set_discoverable:
+ * @client: a #BluetoothClient object
+ * @discoverable: whether the device should be discoverable
+ * @timeout: timeout in seconds for making undiscoverable, or 0 for never
+ *
+ * Sets the default adapter's discoverable status.
+ *
+ * Return value: Whether setting the state on the default adapter was successful.
+ **/
+static gboolean
+_bluetooth_client_set_discoverable (BluetoothClient *client,
+				    gboolean discoverable,
+				    guint timeout)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE (client);
+	GError *error = NULL;
+	GtkTreePath *path;
+	Properties *properties;
+	gboolean ret;
+	GtkTreeIter iter;
+
+	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
+
+	if (priv->default_adapter == NULL)
+		return FALSE;
+
+	path = gtk_tree_row_reference_get_path (priv->default_adapter);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+                            BLUETOOTH_COLUMN_PROPERTIES, &properties, -1);
+        gtk_tree_path_free (path);
+
+	if (properties == NULL)
+		return FALSE;
+
+	ret = properties_call_set_sync (properties,
+					BLUEZ_ADAPTER_INTERFACE,
+					"Discoverable",
+					g_variant_new_variant (g_variant_new_boolean (discoverable)),
+					NULL, &error);
+	if (ret == FALSE) {
+		g_warning ("Failed to set Discoverable to %d: %s", discoverable, error->message);
+		g_error_free (error);
+	} else {
+		ret = properties_call_set_sync (properties,
+						BLUEZ_ADAPTER_INTERFACE,
+						"DiscoverableTimeout",
+						g_variant_new_variant (g_variant_new_uint32 (timeout)),
+						NULL, &error);
+		if (ret == FALSE) {
+			g_warning ("Failed to set DiscoverableTimeout to %d: %s", timeout, error->message);
+			g_error_free (error);
 		}
 	}
 
-	manager_default_adapter(priv->manager, &default_path, NULL);
-	if (default_path != NULL) {
-		default_adapter_changed(priv->manager, default_path, client);
-		g_free(default_path);
+	g_object_unref (properties);
+
+	return ret;
+}
+
+static void
+_bluetooth_client_set_default_adapter_discovering (BluetoothClient *client,
+						   gboolean         discover)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE (client);
+	GtkTreeIter iter;
+	GDBusProxy *adapter;
+	gboolean current;
+
+	adapter = _bluetooth_client_get_default_adapter (client);
+	if (adapter == NULL)
+		return;
+
+	get_iter_from_proxy (priv->store, &iter, adapter);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+			    BLUETOOTH_COLUMN_DISCOVERING, &current, -1);
+
+	if (current == discover) {
+		g_object_unref(adapter);
+		return;
 	}
+
+	if (discover)
+		adapter1_call_start_discovery_sync (ADAPTER1 (adapter), NULL, NULL);
+	else
+		adapter1_call_stop_discovery_sync (ADAPTER1 (adapter), NULL, NULL);
+
+	g_object_unref(adapter);
+}
+
+static gboolean
+_bluetooth_client_get_default_adapter_discovering (BluetoothClient *self)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE (self);
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gboolean ret;
+
+	if (priv->default_adapter == NULL)
+		return FALSE;
+
+	path = gtk_tree_row_reference_get_path (priv->default_adapter);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter, BLUETOOTH_COLUMN_DISCOVERING, &ret, -1);
+	gtk_tree_path_free (path);
+
+	return ret;
 }
 
 static void
@@ -1202,14 +1167,23 @@ bluetooth_client_get_property (GObject        *object,
 			       GValue         *value,
 			       GParamSpec     *pspec)
 {
-	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(object);
+	BluetoothClient *self = BLUETOOTH_CLIENT (object);
 
 	switch (property_id) {
 	case PROP_DEFAULT_ADAPTER:
-		g_value_set_string (value, priv->default_adapter);
+		g_value_set_string (value, _bluetooth_client_get_default_adapter_path (self));
 		break;
 	case PROP_DEFAULT_ADAPTER_POWERED:
-		g_value_set_boolean (value, priv->default_adapter_powered);
+		g_value_set_boolean (value, _bluetooth_client_get_default_adapter_powered (self));
+		break;
+	case PROP_DEFAULT_ADAPTER_NAME:
+		g_value_take_string (value, _bluetooth_client_get_default_adapter_name (self));
+		break;
+	case PROP_DEFAULT_ADAPTER_DISCOVERABLE:
+		g_value_set_boolean (value, _bluetooth_client_get_discoverable (self));
+		break;
+	case PROP_DEFAULT_ADAPTER_DISCOVERING:
+		g_value_set_boolean (value, _bluetooth_client_get_default_adapter_discovering (self));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
@@ -1217,28 +1191,37 @@ bluetooth_client_get_property (GObject        *object,
 	}
 }
 
-static void bluetooth_client_finalize(GObject *client)
+static void
+bluetooth_client_set_property (GObject        *object,
+			       guint           property_id,
+			       const GValue   *value,
+			       GParamSpec     *pspec)
 {
-	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	BluetoothClient *self = BLUETOOTH_CLIENT (object);
 
-	DBG("client %p", client);
+	switch (property_id) {
+	case PROP_DEFAULT_ADAPTER_DISCOVERABLE:
+	        _bluetooth_client_set_discoverable (self, g_value_get_boolean (value), 0);
+		break;
+	case PROP_DEFAULT_ADAPTER_DISCOVERING:
+		_bluetooth_client_set_default_adapter_discovering (self, g_value_get_boolean (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+		break;
+	}
+}
 
-	g_signal_handlers_disconnect_by_func(priv->dbus,
-					name_owner_changed, client);
-	g_object_unref(priv->dbus);
+static void bluetooth_client_finalize(GObject *client)
+{
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 
-	g_signal_handlers_disconnect_by_func(priv->manager,
-						adapter_added, client);
-	g_signal_handlers_disconnect_by_func(priv->manager,
-						adapter_removed, client);
-	g_signal_handlers_disconnect_by_func(priv->manager,
-					default_adapter_changed, client);
-	g_object_unref(priv->manager);
+	g_bus_unwatch_name (priv->owner_change_id);
 
-	g_object_unref(priv->store);
+	g_clear_object (&priv->manager);
+	g_object_unref (priv->store);
 
-	g_free (priv->default_adapter);
-	priv->default_adapter = NULL;
+	g_clear_pointer (&priv->default_adapter, gtk_tree_row_reference_free);
 
 	G_OBJECT_CLASS(bluetooth_client_parent_class)->finalize(client);
 }
@@ -1246,42 +1229,83 @@ static void bluetooth_client_finalize(GObject *client)
 static void bluetooth_client_class_init(BluetoothClientClass *klass)
 {
 	GObjectClass *object_class = (GObjectClass *) klass;
-	GError *error = NULL;
-
-	DBG("class %p", klass);
 
 	g_type_class_add_private(klass, sizeof(BluetoothClientPrivate));
 
 	object_class->finalize = bluetooth_client_finalize;
 	object_class->get_property = bluetooth_client_get_property;
-
-
+	object_class->set_property = bluetooth_client_set_property;
+
+	/**
+	 * BluetoothClient::device-removed:
+	 * @client: a #BluetoothClient object which received the signal
+	 * @device: the D-Bus object path for the now-removed device
+	 *
+	 * The #BluetoothClient::device-removed signal is launched when a
+	 * device gets removed from the model.
+	 **/
+	signals[DEVICE_REMOVED] =
+		g_signal_new ("device-removed",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__STRING,
+			      G_TYPE_NONE, 1, G_TYPE_STRING);
+
+	/**
+	 * BluetoothClient:default-adapter:
+	 *
+	 * The D-Bus path of the default Bluetooth adapter or %NULL.
+	 */
 	g_object_class_install_property (object_class, PROP_DEFAULT_ADAPTER,
-					 g_param_spec_string ("default-adapter", NULL, NULL,
+					 g_param_spec_string ("default-adapter", NULL,
+							      "The D-Bus path of the default adapter",
 							      NULL, G_PARAM_READABLE));
+	/**
+	 * BluetoothClient:default-adapter-powered:
+	 *
+	 * %TRUE if the default Bluetooth adapter is powered.
+	 */
 	g_object_class_install_property (object_class, PROP_DEFAULT_ADAPTER_POWERED,
-					 g_param_spec_boolean ("default-adapter-powered", NULL, NULL,
-					 		       FALSE, G_PARAM_READABLE));
-
-	dbus_g_object_register_marshaller(marshal_VOID__STRING_BOXED,
-						G_TYPE_NONE, G_TYPE_STRING,
-						G_TYPE_VALUE, G_TYPE_INVALID);
-
-	connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-
-	if (error != NULL) {
-		g_printerr("Connecting to system bus failed: %s\n",
-							error->message);
-		g_error_free(error);
-	}
+					 g_param_spec_boolean ("default-adapter-powered", NULL,
+							      "Whether the default adapter is powered",
+							       FALSE, G_PARAM_READABLE));
+	/**
+	 * BluetoothClient:default-adapter-discoverable:
+	 *
+	 * %TRUE if the default Bluetooth adapter is discoverable.
+	 */
+	g_object_class_install_property (object_class, PROP_DEFAULT_ADAPTER_DISCOVERABLE,
+					 g_param_spec_boolean ("default-adapter-discoverable", NULL,
+							      "Whether the default adapter is visible by other devices",
+							       FALSE, G_PARAM_READWRITE));
+	/**
+	 * BluetoothClient:default-adapter-name:
+	 *
+	 * The name of the default Bluetooth adapter or %NULL.
+	 */
+	g_object_class_install_property (object_class, PROP_DEFAULT_ADAPTER_NAME,
+					 g_param_spec_string ("default-adapter-name", NULL,
+							      "The human readable name of the default adapter",
+							      NULL, G_PARAM_READABLE));
+	/**
+	 * BluetoothClient:default-adapter-discovering:
+	 *
+	 * %TRUE if the default Bluetooth adapter is discovering.
+	 */
+	g_object_class_install_property (object_class, PROP_DEFAULT_ADAPTER_DISCOVERING,
+					 g_param_spec_boolean ("default-adapter-discovering", NULL,
+							      "Whether the default adapter is searching for devices",
+							       FALSE, G_PARAM_READWRITE));
 }
 
 /**
  * bluetooth_client_new:
  *
- * Returns a reference to the #BluetoothClient singleton. Use #g_object_unref() the object when done.
+ * Returns a reference to the #BluetoothClient singleton. Use g_object_unref() when done with the object.
  *
- * Return value: a #BluetoothClient object.
+ * Return value: (transfer full): a #BluetoothClient object.
  **/
 BluetoothClient *bluetooth_client_new(void)
 {
@@ -1294,8 +1318,6 @@ BluetoothClient *bluetooth_client_new(void)
 	g_object_add_weak_pointer (G_OBJECT (bluetooth_client),
 				   (gpointer) &bluetooth_client);
 
-	DBG("client %p", bluetooth_client);
-
 	return bluetooth_client;
 }
 
@@ -1305,7 +1327,7 @@ BluetoothClient *bluetooth_client_new(void)
  *
  * Returns an unfiltered #GtkTreeModel representing the adapter and devices available on the system.
  *
- * Return value: a #GtkTreeModel object.
+ * Return value: (transfer full): a #GtkTreeModel object.
  **/
 GtkTreeModel *bluetooth_client_get_model (BluetoothClient *client)
 {
@@ -1314,8 +1336,6 @@ GtkTreeModel *bluetooth_client_get_model (BluetoothClient *client)
 
 	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), NULL);
 
-	DBG("client %p", client);
-
 	priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 	model = g_object_ref(priv->store);
 
@@ -1329,9 +1349,9 @@ GtkTreeModel *bluetooth_client_get_model (BluetoothClient *client)
  * @data: user data to pass to gtk_tree_model_filter_set_visible_func()
  * @destroy: a destroy function for gtk_tree_model_filter_set_visible_func()
  *
- * Returns a #GtkTreeModel of devices filtered using the @func, @data and @destroy arguments to pass to gtk_tree_model_filter_set_visible_func().
+ * Returns a #GtkTreeModelFilter of devices filtered using the @func, @data and @destroy arguments to pass to gtk_tree_model_filter_set_visible_func().
  *
- * Return value: a #GtkTreeModel object.
+ * Return value: (transfer full): a #GtkTreeModel object.
  **/
 GtkTreeModel *bluetooth_client_get_filter_model (BluetoothClient *client,
 						 GtkTreeModelFilterVisibleFunc func,
@@ -1342,8 +1362,6 @@ GtkTreeModel *bluetooth_client_get_filter_model (BluetoothClient *client,
 
 	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), NULL);
 
-	DBG("client %p", client);
-
 	priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
 	model = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->store), NULL);
 
@@ -1356,7 +1374,7 @@ GtkTreeModel *bluetooth_client_get_filter_model (BluetoothClient *client,
 static gboolean adapter_filter(GtkTreeModel *model,
 					GtkTreeIter *iter, gpointer user_data)
 {
-	DBusGProxy *proxy;
+	GDBusProxy *proxy;
 	gboolean active;
 
 	gtk_tree_model_get(model, iter, BLUETOOTH_COLUMN_PROXY, &proxy, -1);
@@ -1365,7 +1383,7 @@ static gboolean adapter_filter(GtkTreeModel *model,
 		return FALSE;
 
 	active = g_str_equal(BLUEZ_ADAPTER_INTERFACE,
-					dbus_g_proxy_get_interface(proxy));
+					g_dbus_proxy_get_interface_name(proxy));
 
 	g_object_unref(proxy);
 
@@ -1376,14 +1394,12 @@ static gboolean adapter_filter(GtkTreeModel *model,
  * bluetooth_client_get_adapter_model:
  * @client: a #BluetoothClient object
  *
- * Returns a filtered #GtkTreeModel with only adapters present.
+ * Returns a #GtkTreeModelFilter with only adapters present.
  *
- * Return value: a #GtkTreeModel object.
+ * Return value: (transfer full): a #GtkTreeModel object.
  **/
 GtkTreeModel *bluetooth_client_get_adapter_model (BluetoothClient *client)
 {
-	DBG("client %p", client);
-
 	return bluetooth_client_get_filter_model (client, adapter_filter,
 						  NULL, NULL);
 }
@@ -1391,14 +1407,15 @@ GtkTreeModel *bluetooth_client_get_adapter_model (BluetoothClient *client)
 /**
  * bluetooth_client_get_device_model:
  * @client: a #BluetoothClient object
- * @adapter: a #DBusGProxy of the adapter object, or %NULL to get the default adapter.
  *
- * Returns a filtered #GtkTreeModel with only devices belonging to the selected adapter listed. Note that the model will follow a specific adapter, and will not follow the default-adapter when %NULL is passed.
+ * Returns a #GtkTreeModelFilter with only devices belonging to the default adapter listed.
+ * Note that the model will follow a specific adapter, and will not follow the default adapter.
+ * Also note that due to the way #GtkTreeModelFilter works, you will probably want to
+ * monitor signals on the "child-model" #GtkTreeModel to monitor for changes.
  *
- * Return value: a #GtkTreeModel object.
+ * Return value: (transfer full): a #GtkTreeModel object.
  **/
-GtkTreeModel *bluetooth_client_get_device_model (BluetoothClient *client,
-						 DBusGProxy *adapter)
+GtkTreeModel *bluetooth_client_get_device_model (BluetoothClient *client)
 {
 	BluetoothClientPrivate *priv;
 	GtkTreeModel *model;
@@ -1408,601 +1425,349 @@ GtkTreeModel *bluetooth_client_get_device_model (BluetoothClient *client,
 
 	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), NULL);
 
-	DBG("client %p", client);
-
 	priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	cont = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(priv->store),
-									&iter);
+	cont = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(priv->store), &iter);
 
 	while (cont == TRUE) {
-		DBusGProxy *proxy;
 		gboolean is_default;
 
-		gtk_tree_model_get(GTK_TREE_MODEL(priv->store), &iter,
-				BLUETOOTH_COLUMN_PROXY, &proxy,
-				BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
-
-		if (adapter == NULL && is_default == TRUE)
-			found = TRUE;
+		gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+				    BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
 
-		if (proxy == adapter)
+		if (is_default == TRUE) {
 			found = TRUE;
-
-		g_object_unref(proxy);
-
-		if (found == TRUE)
 			break;
+		}
 
-		cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(priv->store),
-									&iter);
+		cont = gtk_tree_model_iter_next (GTK_TREE_MODEL(priv->store), &iter);
 	}
 
 	if (found == TRUE) {
-		path = gtk_tree_model_get_path(GTK_TREE_MODEL(priv->store),
-									&iter);
-		model = gtk_tree_model_filter_new(GTK_TREE_MODEL(priv->store),
-									path);
-		gtk_tree_path_free(path);
+		path = gtk_tree_model_get_path (GTK_TREE_MODEL(priv->store), &iter);
+		model = gtk_tree_model_filter_new (GTK_TREE_MODEL(priv->store), path);
+		gtk_tree_path_free (path);
 	} else
 		model = NULL;
 
 	return model;
 }
 
-/**
- * bluetooth_client_get_device_filter_model:
- * @client: a #BluetoothClient object
- * @adapter: a #DBusGProxy representing a particular adapter, or %NULL for the default adapter.
- * @func: a #GtkTreeModelFilterVisibleFunc
- * @data: user data to pass to gtk_tree_model_filter_set_visible_func()
- * @destroy: a destroy function for gtk_tree_model_filter_set_visible_func()
- *
- * Returns a #GtkTreeModel of adapters filtered using the @func, @data and
- * @destroy arguments to pass to gtk_tree_model_filter_set_visible_func().
- *
- * Return value: a #GtkTreeModel object.
- **/
-GtkTreeModel *bluetooth_client_get_device_filter_model(BluetoothClient *client,
-		DBusGProxy *adapter, GtkTreeModelFilterVisibleFunc func,
-				gpointer data, GDestroyNotify destroy)
-{
-	GtkTreeModel *model;
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), NULL);
-
-	DBG("client %p", client);
-
-	model = bluetooth_client_get_device_model(client, adapter);
-
-	gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model),
-							func, data, destroy);
-
-	return model;
-}
+typedef struct {
+	BluetoothClientSetupFunc func;
+	BluetoothClient *client;
+} CreateDeviceData;
 
-/**
- * bluetooth_client_get_default_adapter:
- * @client: a #BluetoothClient object
- *
- * Returns a #DBusGProxy object representing the default adapter, or %NULL if no adapters are present.
- *
- * Return value: a #DBusGProxy object.
- **/
-DBusGProxy *bluetooth_client_get_default_adapter(BluetoothClient *client)
+static void
+device_pair_callback (GDBusProxy         *proxy,
+		      GAsyncResult       *res,
+		      GSimpleAsyncResult *simple)
 {
-	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	GtkTreeIter iter;
-	gboolean cont;
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), NULL);
-
-	DBG("client %p", client);
-
-	cont = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(priv->store),
-									&iter);
-
-	while (cont == TRUE) {
-		DBusGProxy *adapter;
-		gboolean is_default;
-
-		gtk_tree_model_get(GTK_TREE_MODEL(priv->store), &iter,
-				BLUETOOTH_COLUMN_PROXY, &adapter,
-				BLUETOOTH_COLUMN_DEFAULT, &is_default, -1);
-
-		if (is_default == TRUE)
-			return adapter;
-
-		g_object_unref(adapter);
+	GError *error = NULL;
 
-		cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(priv->store),
-									&iter);
+	if (device1_call_pair_finish (DEVICE1(proxy), res, &error) == FALSE) {
+		g_debug ("Pair() failed for %s: %s",
+			 g_dbus_proxy_get_object_path (proxy),
+			 error->message);
+		g_simple_async_result_take_error (simple, error);
+	} else {
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
 	}
 
-	return NULL;
-}
-
-/**
- * bluetooth_client_start_discovery:
- * @client: a #BluetoothClient object
- *
- * Start a discovery on the default adapter.
- *
- * Return value: Whether a discovery was successfully started on the default adapter.
- **/
-gboolean bluetooth_client_start_discovery(BluetoothClient *client)
-{
-	DBusGProxy *adapter;
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
-
-	DBG("client %p", client);
-
-	adapter = bluetooth_client_get_default_adapter(client);
-	if (adapter == NULL)
-		return FALSE;
-
-	adapter_start_discovery(adapter, NULL);
-
-	g_object_unref(adapter);
+	g_simple_async_result_complete_in_idle (simple);
 
-	return TRUE;
+	g_object_unref (simple);
 }
 
-/**
- * bluetooth_client_stop_discovery:
- * @client: a #BluetoothClient object
- *
- * Stop a discovery started on the default adapter.
- *
- * Return value: Whether a discovery was successfully stopped on the default adapter.
- **/
-gboolean bluetooth_client_stop_discovery(BluetoothClient *client)
-{
-	DBusGProxy *adapter;
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
-
-	DBG("client %p", client);
-
-	adapter = bluetooth_client_get_default_adapter(client);
-	if (adapter == NULL)
-		return FALSE;
-
-	adapter_stop_discovery(adapter, NULL);
-
-	g_object_unref(adapter);
-
-	return TRUE;
-}
-
-/**
- * bluetooth_client_set_discoverable:
- * @client: a #BluetoothClient object
- * @discoverable: whether the device should be discoverable
- *
- * Sets the default adapter's discoverable status.
- *
- * Return value: Whether setting the state on the default adapter was successful.
- **/
 gboolean
-bluetooth_client_set_discoverable (BluetoothClient *client,
-				   gboolean discoverable)
+bluetooth_client_setup_device_finish (BluetoothClient  *client,
+				      GAsyncResult     *res,
+				      char            **path,
+				      GError          **error)
 {
-	DBusGProxy *adapter;
-	GValue disco = { 0 };
-	GValue timeout = { 0 };
-	gboolean ret;
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
-
-	DBG("client %p", client);
-
-	adapter = bluetooth_client_get_default_adapter (client);
-	if (adapter == NULL)
-		return FALSE;
-
-	g_value_init (&disco, G_TYPE_BOOLEAN);
-	g_value_init (&timeout, G_TYPE_UINT);
-
-	g_value_set_boolean (&disco, discoverable);
-	g_value_set_uint (&timeout, 0);
+	GSimpleAsyncResult *simple;
 
-	ret = dbus_g_proxy_call (adapter, "SetProperty", NULL,
-				 G_TYPE_STRING, "Discoverable",
-				 G_TYPE_VALUE, &disco,
-				 G_TYPE_INVALID, G_TYPE_INVALID);
-	if (ret == FALSE)
-		goto bail;
+	simple = (GSimpleAsyncResult *) res;
 
-	ret = dbus_g_proxy_call (adapter, "SetProperty", NULL,
-				 G_TYPE_STRING, "DiscoverableTimeout",
-				 G_TYPE_VALUE, &timeout,
-				 G_TYPE_INVALID, G_TYPE_INVALID);
+	g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == bluetooth_client_setup_device);
 
-bail:
-	g_value_unset (&disco);
-	g_value_unset (&timeout);
+	if (path != NULL)
+		*path = g_object_get_data (G_OBJECT (res), "device-object-path");
 
-	g_object_unref(adapter);
-
-	return ret;
+	if (g_simple_async_result_get_op_res_gboolean (simple))
+		return TRUE;
+	g_simple_async_result_propagate_error (simple, error);
+	return FALSE;
 }
 
-typedef struct {
-	BluetoothClientCreateDeviceFunc func;
-	gpointer data;
-	BluetoothClient *client;
-} CreateDeviceData;
-
-static void create_device_callback(DBusGProxy *proxy,
-					DBusGProxyCall *call, void *user_data)
-{
-	CreateDeviceData *devdata = user_data;
-	GError *error = NULL;
-	char *path = NULL;
-
-	dbus_g_proxy_end_call(proxy, call, &error,
-			DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID);
-
-	if (error != NULL)
-		path = NULL;
-
-	if (devdata->func)
-		devdata->func(devdata->client, path, error, devdata->data);
-
-	if (error != NULL)
-		g_error_free (error);
-
-	g_object_unref (devdata->client);
-	g_object_unref(proxy);
-}
-
-gboolean bluetooth_client_create_device (BluetoothClient *client,
-					 const char *address,
-					 const char *agent,
-					 BluetoothClientCreateDeviceFunc func,
-					 gpointer data)
+void
+bluetooth_client_setup_device (BluetoothClient          *client,
+			       const char               *path,
+			       gboolean                  pair,
+			       GCancellable             *cancellable,
+			       GAsyncReadyCallback       callback,
+			       gpointer                  user_data)
 {
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	CreateDeviceData *devdata;
-	DBusGProxy *adapter;
-	GtkTreeIter iter;
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
-	g_return_val_if_fail (address != NULL, FALSE);
-
-	DBG("client %p", client);
-
-	adapter = bluetooth_client_get_default_adapter(client);
-	if (adapter == NULL)
-		return FALSE;
-
-	/* Remove the pairing if it already exists, but only for pairings */
-	if (agent != NULL &&
-	    get_iter_from_address(priv->store, &iter, address, adapter) == TRUE) {
-		DBusGProxy *device;
-		gboolean paired;
-		GError *err = NULL;
+	GSimpleAsyncResult *simple;
+	GDBusProxy *device;
+	GtkTreeIter iter, adapter_iter;
+	gboolean paired;
+	GError *err = NULL;
+
+	g_return_if_fail (BLUETOOTH_IS_CLIENT (client));
+
+	simple = g_simple_async_result_new (G_OBJECT (client),
+					    callback,
+					    user_data,
+					    bluetooth_client_setup_device);
+	g_simple_async_result_set_check_cancellable (simple, cancellable);
+	g_object_set_data (G_OBJECT (simple), "device-object-path", g_strdup (path));
+
+	if (get_iter_from_path (priv->store, &iter, path) == FALSE) {
+		g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+						 "Device with object path %s does not exist",
+						 path);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
+		return;
+	}
 
-		gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
-				    BLUETOOTH_COLUMN_PROXY, &device,
-				    BLUETOOTH_COLUMN_PAIRED, &paired, -1);
-		if (paired != FALSE &&
-		    dbus_g_proxy_call (adapter, "RemoveDevice", &err,
-				       DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (device),
-				       G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
-			g_warning ("Failed to remove device '%s': %s", address,
-				   err->message);
+	gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+			    BLUETOOTH_COLUMN_PROXY, &device,
+			    BLUETOOTH_COLUMN_PAIRED, &paired, -1);
+
+	if (paired != FALSE &&
+	    gtk_tree_model_iter_parent (GTK_TREE_MODEL(priv->store), &adapter_iter, &iter)) {
+		GDBusProxy *adapter;
+
+		gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &adapter_iter,
+				    BLUETOOTH_COLUMN_PROXY, &adapter,
+				    -1);
+		adapter1_call_remove_device_sync (ADAPTER1 (adapter),
+						  path,
+						  NULL, &err);
+		if (err != NULL) {
+			g_warning ("Failed to remove device: %s", err->message);
 			g_error_free (err);
 		}
-		if (device != NULL)
-			g_object_unref (device);
+		g_object_unref (adapter);
 	}
 
-	devdata = g_try_new0(CreateDeviceData, 1);
-	if (devdata == NULL)
-		return FALSE;
-
-	devdata->func = func;
-	devdata->data = data;
-	devdata->client = g_object_ref (client);
-
-	if (agent != NULL)
-		dbus_g_proxy_begin_call_with_timeout(adapter,
-						     "CreatePairedDevice", create_device_callback,
-						     devdata, g_free, 90 * 1000,
-						     G_TYPE_STRING, address,
-						     DBUS_TYPE_G_OBJECT_PATH, agent,
-						     G_TYPE_STRING, "DisplayYesNo", G_TYPE_INVALID);
-	else
-		dbus_g_proxy_begin_call_with_timeout(adapter,
-						     "CreateDevice", create_device_callback,
-						     devdata, g_free, 60 * 1000,
-						     G_TYPE_STRING, address, G_TYPE_INVALID);
-
-	return TRUE;
-}
-
-gboolean bluetooth_client_set_trusted(BluetoothClient *client,
-					const char *device, gboolean trusted)
-{
-	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	DBusGProxy *proxy;
-	GValue value = { 0 };
-
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
-	g_return_val_if_fail (device != NULL, FALSE);
-
-	DBG("client %p", client);
-
-	proxy = dbus_g_proxy_new_from_proxy(priv->manager,
-					BLUEZ_DEVICE_INTERFACE, device);
-	if (proxy == NULL)
-		return FALSE;
-
-	g_value_init(&value, G_TYPE_BOOLEAN);
-	g_value_set_boolean(&value, trusted);
-
-	dbus_g_proxy_call(proxy, "SetProperty", NULL,
-					G_TYPE_STRING, "Trusted",
-					G_TYPE_VALUE, &value,
-					G_TYPE_INVALID, G_TYPE_INVALID);
-
-	g_value_unset(&value);
-
-	g_object_unref(proxy);
-
-	return TRUE;
-}
-
-typedef struct {
-	BluetoothClientConnectFunc func;
-	gpointer data;
-	BluetoothClient *client;
-	/* used for disconnect */
-	GList *services;
-} ConnectData;
-
-static void connect_callback(DBusGProxy *proxy,
-			     DBusGProxyCall *call, void *user_data)
-{
-	ConnectData *conndata = user_data;
-	GError *error = NULL;
-	gboolean retval = TRUE;
-
-	dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INVALID);
-
-	if (error != NULL) {
-		retval = FALSE;
-		g_error_free(error);
+	if (pair == TRUE) {
+		device1_call_pair (DEVICE1(device),
+				   cancellable,
+				   (GAsyncReadyCallback) device_pair_callback,
+				   simple);
+	} else {
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+		g_simple_async_result_complete_in_idle (simple);
+		g_object_unref (simple);
 	}
 
-	if (conndata->func)
-		conndata->func(conndata->client, retval, conndata->data);
-
-	g_object_unref (conndata->client);
-	g_object_unref(proxy);
+	g_object_unref (device);
 }
 
-gboolean bluetooth_client_connect_service(BluetoothClient *client,
-					  const char *device,
-					  BluetoothClientConnectFunc func,
-					  gpointer data)
+gboolean
+bluetooth_client_set_trusted (BluetoothClient *client,
+			      const char      *device,
+			      gboolean         trusted)
 {
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	ConnectData *conndata;
-	DBusGProxy *proxy;
-	GHashTable *table;
+	Properties *properties;
+	GError     *error = NULL;
 	GtkTreeIter iter;
-	const char *iface_name;
-	guint i;
+	gboolean   ret;
 
 	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
 	g_return_val_if_fail (device != NULL, FALSE);
 
-	DBG("client %p", client);
-
-	if (get_iter_from_path (priv->store, &iter, device) == FALSE)
-		return FALSE;
-
-	gtk_tree_model_get(GTK_TREE_MODEL (priv->store), &iter,
-			   BLUETOOTH_COLUMN_SERVICES, &table,
-			   -1);
-	if (table == NULL)
+	if (get_iter_from_path (priv->store, &iter, device) == FALSE) {
+		g_debug ("Couldn't find device '%s' in tree to mark it as trusted", device);
 		return FALSE;
-
-	conndata = g_new0 (ConnectData, 1);
-
-	iface_name = NULL;
-	for (i = 0; i < G_N_ELEMENTS (connectable_interfaces); i++) {
-		if (g_hash_table_lookup_extended (table, connectable_interfaces[i], NULL, NULL) != FALSE) {
-			iface_name = connectable_interfaces[i];
-			break;
-		}
 	}
-	g_hash_table_unref (table);
 
-	if (iface_name == NULL) {
-		g_printerr("No supported services on the '%s' device\n", device);
-		g_free (conndata);
-		return FALSE;
-	}
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
+			    BLUETOOTH_COLUMN_PROPERTIES, &properties, -1);
 
-	proxy = dbus_g_proxy_new_from_proxy(priv->manager,
-						iface_name, device);
-	if (proxy == NULL) {
-		g_free (conndata);
+	if (properties == NULL) {
+		g_debug ("Couldn't find properties for device '%s' in tree to mark it as trusted", device);
 		return FALSE;
 	}
 
-	conndata->func = func;
-	conndata->data = data;
-	conndata->client = g_object_ref (client);
-
-	dbus_g_proxy_begin_call(proxy, "Connect",
-				connect_callback, conndata, g_free,
-				G_TYPE_INVALID);
+	ret = properties_call_set_sync (properties, BLUEZ_DEVICE_INTERFACE, "Trusted",
+					g_variant_new_variant (g_variant_new_boolean (trusted)),
+					NULL, &error);
+	if (ret == FALSE) {
+		g_warning ("Failed to set Trusted to %d: %s", trusted, error->message);
+		g_error_free (error);
+	}
 
-	return TRUE;
+	g_object_unref (properties);
+	return ret;
 }
 
-static void disconnect_callback(DBusGProxy *proxy,
-				DBusGProxyCall *call,
-				void *user_data)
+GDBusProxy *
+bluetooth_client_get_device (BluetoothClient *client,
+			     const char       *path)
 {
-	ConnectData *conndata = user_data;
-
-	dbus_g_proxy_end_call(proxy, call, NULL, G_TYPE_INVALID);
-
-	if (conndata->services != NULL) {
-		DBusGProxy *service;
-
-		service = dbus_g_proxy_new_from_proxy (proxy,
-						       conndata->services->data, NULL);
-
-		conndata->services = g_list_remove (conndata->services, conndata->services->data);
-
-		dbus_g_proxy_begin_call(service, "Disconnect",
-					disconnect_callback, conndata, NULL,
-					G_TYPE_INVALID);
-
-		g_object_unref (proxy);
+	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
+	GtkTreeIter iter;
+	GDBusProxy *proxy;
 
-		return;
+	if (get_iter_from_path (priv->store, &iter, path) == FALSE) {
+		return NULL;
 	}
 
-	if (conndata->func)
-		conndata->func(conndata->client, TRUE, conndata->data);
-
-	g_object_unref (conndata->client);
-	g_object_unref(proxy);
-	g_free (conndata);
+	gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+			                BLUETOOTH_COLUMN_PROXY, &proxy,
+			                -1);
+	return proxy;
 }
 
-static int
-service_to_index (const char *service)
+static void
+connect_callback (GDBusProxy         *proxy,
+		  GAsyncResult       *res,
+		  GSimpleAsyncResult *simple)
 {
-	guint i;
-
-	g_return_val_if_fail (service != NULL, -1);
+	gboolean retval;
+	GError *error = NULL;
 
-	for (i = 0; i < G_N_ELEMENTS (connectable_interfaces); i++) {
-		if (g_str_equal (connectable_interfaces[i], service) != FALSE)
-			return i;
-	}
-	for (i = 0; i < G_N_ELEMENTS (detectable_interfaces); i++) {
-		if (g_str_equal (detectable_interfaces[i], service) != FALSE)
-			return i + G_N_ELEMENTS (connectable_interfaces);
+	retval = device1_call_connect_finish (DEVICE1(proxy), res, &error);
+	if (retval == FALSE) {
+		g_debug ("Connect failed for %s: %s",
+			 g_dbus_proxy_get_object_path (proxy), error->message);
+		g_simple_async_result_take_error (simple, error);
+	} else {
+		g_debug ("Connect succeeded for %s",
+			 g_dbus_proxy_get_object_path (proxy));
+		g_simple_async_result_set_op_res_gboolean (simple, retval);
 	}
 
-	g_assert_not_reached ();
+	g_simple_async_result_complete_in_idle (simple);
 
-	return -1;
+	g_object_unref (simple);
 }
 
-static int
-rev_sort_services (const char *servicea, const char *serviceb)
+static void
+disconnect_callback (GDBusProxy   *proxy,
+		     GAsyncResult *res,
+		     GSimpleAsyncResult *simple)
 {
-	int a, b;
+	gboolean retval;
+	GError *error = NULL;
+
+	retval = device1_call_disconnect_finish (DEVICE1(proxy), res, &error);
+	if (retval == FALSE) {
+		g_debug ("Disconnect failed for %s: %s",
+			 g_dbus_proxy_get_object_path (proxy),
+			 error->message);
+		g_simple_async_result_take_error (simple, error);
+	} else {
+		g_debug ("Disconnect succeeded for %s",
+			 g_dbus_proxy_get_object_path (proxy));
+		g_simple_async_result_set_op_res_gboolean (simple, retval);
+	}
 
-	a = service_to_index (servicea);
-	b = service_to_index (serviceb);
+	g_simple_async_result_complete_in_idle (simple);
 
-	if (a < b)
-		return 1;
-	if (a > b)
-		return -1;
-	return 0;
+	g_object_unref (simple);
 }
 
-gboolean bluetooth_client_disconnect_service (BluetoothClient *client,
-					      const char *device,
-					      BluetoothClientConnectFunc func,
-					      gpointer data)
+/**
+ * bluetooth_client_connect_service:
+ * @client: a #BluetoothClient
+ * @path: the object path on which to operate
+ * @connect: Whether try to connect or disconnect from services on a device
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the connection is complete
+ * @user_data: the data to pass to callback function
+ *
+ * When the connection operation is finished, @callback will be called. You can
+ * then call bluetooth_client_connect_service_finish() to get the result of the
+ * operation.
+ **/
+void
+bluetooth_client_connect_service (BluetoothClient     *client,
+				  const char          *path,
+				  gboolean             connect,
+				  GCancellable        *cancellable,
+				  GAsyncReadyCallback  callback,
+				  gpointer             user_data)
 {
 	BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-	ConnectData *conndata;
-	DBusGProxy *proxy;
-	GHashTable *table;
 	GtkTreeIter iter;
+	GSimpleAsyncResult *simple;
+	GDBusProxy *device;
 
-	g_return_val_if_fail (BLUETOOTH_IS_CLIENT (client), FALSE);
-	g_return_val_if_fail (device != NULL, FALSE);
+	g_return_if_fail (BLUETOOTH_IS_CLIENT (client));
+	g_return_if_fail (path != NULL);
 
-	DBG("client %p", client);
-
-	if (get_iter_from_path (priv->store, &iter, device) == FALSE)
-		return FALSE;
-
-	gtk_tree_model_get(GTK_TREE_MODEL (priv->store), &iter,
-			   BLUETOOTH_COLUMN_PROXY, &proxy,
-			   BLUETOOTH_COLUMN_SERVICES, &table,
-			   -1);
-	if (proxy == NULL) {
-		if (table != NULL)
-			g_hash_table_unref (table);
-		return FALSE;
-	}
-
-	conndata = g_new0 (ConnectData, 1);
+	if (get_iter_from_path (priv->store, &iter, path) == FALSE)
+		return;
 
-	conndata->func = func;
-	conndata->data = data;
-	conndata->client = g_object_ref (client);
+	gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &iter,
+			    BLUETOOTH_COLUMN_PROXY, &device,
+			    -1);
 
-	if (table == NULL) {
-		dbus_g_proxy_begin_call(proxy, "Disconnect",
-					disconnect_callback, conndata, NULL,
-					G_TYPE_INVALID);
+	simple = g_simple_async_result_new (G_OBJECT (client),
+					    callback,
+					    user_data,
+					    bluetooth_client_connect_service);
+	g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+	if (connect) {
+		device1_call_connect (DEVICE1(device),
+				      cancellable,
+				      (GAsyncReadyCallback) connect_callback,
+				      simple);
 	} else {
-		DBusGProxy *service;
-
-		conndata->services = g_hash_table_get_keys (table);
-		g_hash_table_unref (table);
-		conndata->services = g_list_sort (conndata->services, (GCompareFunc) rev_sort_services);
-
-		service = dbus_g_proxy_new_from_proxy (priv->manager,
-						       conndata->services->data, device);
-
-		conndata->services = g_list_remove (conndata->services, conndata->services->data);
-
-		dbus_g_proxy_begin_call(service, "Disconnect",
-					disconnect_callback, conndata, NULL,
-					G_TYPE_INVALID);
+		device1_call_disconnect (DEVICE1(device),
+					 cancellable,
+					 (GAsyncReadyCallback) disconnect_callback,
+					 simple);
 	}
 
-	return TRUE;
+	g_object_unref (device);
 }
 
-#define BOOL_STR(x) (x ? "True" : "False")
-
-static void
-services_foreach (const char *service, gpointer _value, GString *str)
+/**
+ * bluetooth_client_connect_service_finish:
+ * @client: a #BluetoothClient
+ * @res: a #GAsyncResult
+ * @error: a #GError
+ *
+ * Finishes the connection operation. See bluetooth_client_connect_service().
+ *
+ * Returns: %TRUE if the connection operation succeeded, %FALSE otherwise.
+ **/
+gboolean
+bluetooth_client_connect_service_finish (BluetoothClient *client,
+					 GAsyncResult    *res,
+					 GError         **error)
 {
-	GEnumClass *eclass;
-	GEnumValue *ev;
-	BluetoothStatus status = GPOINTER_TO_INT (_value);
+	GSimpleAsyncResult *simple;
+
+	simple = (GSimpleAsyncResult *) res;
 
-	eclass = g_type_class_ref (BLUETOOTH_TYPE_STATUS);
-	ev = g_enum_get_value (eclass, status);
-	if (ev == NULL)
-		g_warning ("Unknown status value %d", status);
+	g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == bluetooth_client_connect_service);
 
-	g_string_append_printf (str, "%s (%s) ", service, ev ? ev->value_nick : "unknown");
-	g_type_class_unref (eclass);
+	if (g_simple_async_result_get_op_res_gboolean (simple))
+		return TRUE;
+	g_simple_async_result_propagate_error (simple, error);
+	return FALSE;
 }
 
+#define BOOL_STR(x) (x ? "True" : "False")
+
 void
 bluetooth_client_dump_device (GtkTreeModel *model,
-			      GtkTreeIter *iter,
-			      gboolean recurse)
+			      GtkTreeIter *iter)
 {
-	DBusGProxy *proxy;
+	GDBusProxy *proxy;
 	char *address, *alias, *name, *icon, **uuids;
 	gboolean is_default, paired, trusted, connected, discoverable, discovering, powered, is_adapter;
-	GHashTable *services;
 	GtkTreeIter parent;
-	guint type;
+	BluetoothType type;
 
 	gtk_tree_model_get (model, iter,
 			    BLUETOOTH_COLUMN_ADDRESS, &address,
@@ -2017,17 +1782,24 @@ bluetooth_client_dump_device (GtkTreeModel *model,
 			    BLUETOOTH_COLUMN_DISCOVERABLE, &discoverable,
 			    BLUETOOTH_COLUMN_DISCOVERING, &discovering,
 			    BLUETOOTH_COLUMN_POWERED, &powered,
-			    BLUETOOTH_COLUMN_SERVICES, &services,
 			    BLUETOOTH_COLUMN_UUIDS, &uuids,
 			    BLUETOOTH_COLUMN_PROXY, &proxy,
 			    -1);
-	is_adapter = !gtk_tree_model_iter_parent (model, &parent, iter);
+	if (proxy) {
+		char *basename;
+		basename = g_path_get_basename(g_dbus_proxy_get_object_path(proxy));
+		is_adapter = !g_str_has_prefix (basename, "dev_");
+		g_free (basename);
+	} else {
+		is_adapter = !gtk_tree_model_iter_parent (model, &parent, iter);
+	}
 
 	if (is_adapter != FALSE) {
 		/* Adapter */
 		g_print ("Adapter: %s (%s)\n", name, address);
 		if (is_default)
 			g_print ("\tDefault adapter\n");
+		g_print ("\tD-Bus Path: %s\n", proxy ? g_dbus_proxy_get_object_path (proxy) : "(none)");
 		g_print ("\tDiscoverable: %s\n", BOOL_STR (discoverable));
 		if (discovering)
 			g_print ("\tDiscovery in progress\n");
@@ -2035,17 +1807,9 @@ bluetooth_client_dump_device (GtkTreeModel *model,
 	} else {
 		/* Device */
 		g_print ("Device: %s (%s)\n", alias, address);
-		g_print ("\tD-Bus Path: %s\n", proxy ? dbus_g_proxy_get_path (proxy) : "(none)");
+		g_print ("\tD-Bus Path: %s\n", proxy ? g_dbus_proxy_get_object_path (proxy) : "(none)");
 		g_print ("\tType: %s Icon: %s\n", bluetooth_type_to_string (type), icon);
 		g_print ("\tPaired: %s Trusted: %s Connected: %s\n", BOOL_STR(paired), BOOL_STR(trusted), BOOL_STR(connected));
-		if (services != NULL) {
-			GString *str;
-
-			str = g_string_new (NULL);
-			g_hash_table_foreach (services, (GHFunc) services_foreach, str);
-			g_print ("\tServices: %s\n", str->str);
-			g_string_free (str, TRUE);
-		}
 		if (uuids != NULL) {
 			guint i;
 			g_print ("\tUUIDs: ");
@@ -2059,24 +1823,7 @@ bluetooth_client_dump_device (GtkTreeModel *model,
 	g_free (alias);
 	g_free (address);
 	g_free (icon);
-	if (proxy != NULL)
-		g_object_unref (proxy);
-	if (services != NULL)
-		g_hash_table_unref (services);
+	g_clear_object (&proxy);
 	g_strfreev (uuids);
-
-	if (recurse == FALSE)
-		return;
-
-	if (is_adapter != FALSE) {
-		GtkTreeIter child;
-
-		if (gtk_tree_model_iter_children (model, &child, iter) == FALSE)
-			return;
-		bluetooth_client_dump_device (model, &child, FALSE);
-		while (gtk_tree_model_iter_next (model, &child))
-			bluetooth_client_dump_device (model, &child, FALSE);
-	}
-
 }
 
diff --git a/lib/bluetooth-client.h b/lib/bluetooth-client.h
index d375d27..ab4cfa2 100644
--- a/lib/bluetooth-client.h
+++ b/lib/bluetooth-client.h
@@ -26,7 +26,6 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include <dbus/dbus-glib.h>
 #include <bluetooth-enums.h>
 
 G_BEGIN_DECLS
@@ -43,6 +42,12 @@ G_BEGIN_DECLS
 #define BLUETOOTH_GET_CLIENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
 					BLUETOOTH_TYPE_CLIENT, BluetoothClientClass))
 
+/**
+ * BluetoothClient:
+ *
+ * The <structname>BluetoothClient</structname> struct contains
+ * only private fields and should not be directly accessed.
+ */
 typedef struct _BluetoothClient BluetoothClient;
 typedef struct _BluetoothClientClass BluetoothClientClass;
 
@@ -64,15 +69,18 @@ GtkTreeModel *bluetooth_client_get_filter_model(BluetoothClient *client,
 				GtkTreeModelFilterVisibleFunc func,
 				gpointer data, GDestroyNotify destroy);
 GtkTreeModel *bluetooth_client_get_adapter_model(BluetoothClient *client);
-GtkTreeModel *bluetooth_client_get_device_model(BluetoothClient *client,
-							DBusGProxy *adapter);
-GtkTreeModel *bluetooth_client_get_device_filter_model(BluetoothClient *client,
-		DBusGProxy *adapter, GtkTreeModelFilterVisibleFunc func,
-				gpointer data, GDestroyNotify destroy);
+GtkTreeModel *bluetooth_client_get_device_model(BluetoothClient *client);
+
+void bluetooth_client_connect_service (BluetoothClient     *client,
+				       const char          *path,
+				       gboolean             connect,
+				       GCancellable        *cancellable,
+				       GAsyncReadyCallback  callback,
+				       gpointer             user_data);
 
-const gchar *bluetooth_type_to_string(guint type);
-gboolean bluetooth_verify_address (const char *bdaddr);
-const char *bluetooth_uuid_to_string (const char *uuid);
+gboolean bluetooth_client_connect_service_finish (BluetoothClient *client,
+						  GAsyncResult    *res,
+						  GError         **error);
 
 G_END_DECLS
 
diff --git a/lib/bluetooth-client.xml b/lib/bluetooth-client.xml
index 2326277..04bfa5a 100644
--- a/lib/bluetooth-client.xml
+++ b/lib/bluetooth-client.xml
@@ -1,52 +1,59 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/">
-  <interface name="manager">
-    <method name="DefaultAdapter">
-      <arg type="o" direction="out"/>
-    </method>
-
-    <method name="FindAdapter">
-      <arg type="s" name="pattern"/>
-      <arg type="o" direction="out"/>
-    </method>
-
-    <method name="ListAdapters">
-      <arg type="ao" direction="out"/>
-    </method>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node>
+  <interface name="org.bluez.Adapter1">
+    <method name="StartDiscovery"></method>
+    <method name="StopDiscovery"></method>
+    <method name="RemoveDevice"><arg name="device" type="o" direction="in"/></method>
+    <property name="Address" type="s" access="read"></property>
+    <property name="Name" type="s" access="read"></property>
+    <property name="Alias" type="s" access="readwrite"></property>
+    <property name="Class" type="u" access="read"></property>
+    <property name="Powered" type="b" access="readwrite"></property>
+    <property name="Discoverable" type="b" access="readwrite"></property>
+    <property name="DiscoverableTimeout" type="u" access="readwrite"></property>
+    <property name="Pairable" type="b" access="readwrite"></property>
+    <property name="PairableTimeout" type="u" access="readwrite"></property>
+    <property name="Discovering" type="b" access="read"></property>
+    <property name="UUIDs" type="as" access="read"></property>
+    <property name="Modalias" type="s" access="read"></property>
   </interface>
 
-  <interface name="adapter">
-    <method name="GetProperties">
-      <arg type="a{sv}" direction="out"/>
-    </method>
-
-    <method name="StartDiscovery">
-    </method>
-
-    <method name="StopDiscovery">
-    </method>
-
-    <method name="CreateDevice">
-      <arg type="s" name="address"/>
-      <arg type="o" direction="out"/>
-    </method>
+  <interface name="org.bluez.Device1">
+    <method name="Disconnect"></method>
+    <method name="Connect"></method>
+    <method name="ConnectProfile"><arg name="UUID" type="s" direction="in"/> </method>
+    <method name="DisconnectProfile"><arg name="UUID" type="s" direction="in"/> </method>
+    <method name="Pair"></method>
+    <method name="CancelPairing"></method>
+    <property name="Address" type="s" access="read"></property>
+    <property name="Name" type="s" access="read"></property>
+    <property name="Alias" type="s" access="readwrite"></property>
+    <property name="Class" type="u" access="read"></property>
+    <property name="Appearance" type="q" access="read"></property>
+    <property name="Icon" type="s" access="read"></property>
+    <property name="Paired" type="b" access="read"></property>
+    <property name="Trusted" type="b" access="readwrite"></property>
+    <property name="Blocked" type="b" access="readwrite"></property>
+    <property name="LegacyPairing" type="b" access="read"></property>
+    <property name="RSSI" type="n" access="read"></property>
+    <property name="Connected" type="b" access="read"></property>
+    <property name="UUIDs" type="as" access="read"></property>
+    <property name="Modalias" type="s" access="read"></property>
+    <property name="Adapter" type="o" access="read"></property>
+  </interface>
 
-    <method name="CreatePairedDevice">
-      <arg type="s" name="address"/>
-      <arg type="o" name="agent"/>
-      <arg type="s" name="capability"/>
-      <arg type="o" direction="out"/>
+  <interface name="org.bluez.AgentManager1">
+    <method name="RegisterAgent">
+      <arg name="agent" type="o" direction="in"/>
+      <arg name="capability" type="s" direction="in"/>
     </method>
-
-    <method name="RemoveDevice">
-      <arg type="o" name="device"/>
+    <method name="UnregisterAgent">
+      <arg name="agent" type="o" direction="in"/>
     </method>
-  </interface>
-
-  <interface name="device">
-    <method name="GetProperties">
-      <arg type="a{sv}" direction="out"/>
+    <method name="RequestDefaultAgent">
+      <arg name="agent" type="o" direction="in"/>
     </method>
   </interface>
 </node>
diff --git a/lib/bluetooth-enums.h b/lib/bluetooth-enums.h
index aafa65d..3251001 100644
--- a/lib/bluetooth-enums.h
+++ b/lib/bluetooth-enums.h
@@ -53,6 +53,7 @@ typedef enum {
 	BLUETOOTH_CATEGORY_TRUSTED,
 	BLUETOOTH_CATEGORY_NOT_PAIRED_OR_TRUSTED,
 	BLUETOOTH_CATEGORY_PAIRED_OR_TRUSTED,
+	/* < private > */
 	BLUETOOTH_CATEGORY_NUM_CATEGORIES /*< skip >*/
 } BluetoothCategory;
 
@@ -72,6 +73,12 @@ typedef enum {
  * @BLUETOOTH_TYPE_PRINTER: a printer
  * @BLUETOOTH_TYPE_JOYPAD: a joypad, joystick, or other game controller
  * @BLUETOOTH_TYPE_TABLET: a drawing tablet
+ * @BLUETOOTH_TYPE_VIDEO: a video device, such as a webcam
+ * @BLUETOOTH_TYPE_REMOTE_CONTROL: a remote control
+ * @BLUETOOTH_TYPE_SCANNER: a scanner
+ * @BLUETOOTH_TYPE_DISPLAY: a display
+ * @BLUETOOTH_TYPE_WEARABLE: a wearable computer
+ * @BLUETOOTH_TYPE_TOY: a toy or game
  *
  * The type of a Bluetooth device. See also %BLUETOOTH_TYPE_INPUT and %BLUETOOTH_TYPE_AUDIO
  **/
@@ -91,16 +98,32 @@ typedef enum {
 	BLUETOOTH_TYPE_JOYPAD		= 1 << 12,
 	BLUETOOTH_TYPE_TABLET		= 1 << 13,
 	BLUETOOTH_TYPE_VIDEO		= 1 << 14,
+	BLUETOOTH_TYPE_REMOTE_CONTROL	= 1 << 15,
+	BLUETOOTH_TYPE_SCANNER		= 1 << 16,
+	BLUETOOTH_TYPE_DISPLAY		= 1 << 17,
+	BLUETOOTH_TYPE_WEARABLE		= 1 << 18,
+	BLUETOOTH_TYPE_TOY		= 1 << 19
 } BluetoothType;
 
-#define _BLUETOOTH_TYPE_NUM_TYPES 15
+#define _BLUETOOTH_TYPE_NUM_TYPES 20
 
+/**
+ * BLUETOOTH_TYPE_INPUT:
+ *
+ * Use this value to select any Bluetooth input device where a #BluetoothType enum is required.
+ */
 #define BLUETOOTH_TYPE_INPUT (BLUETOOTH_TYPE_KEYBOARD | BLUETOOTH_TYPE_MOUSE | BLUETOOTH_TYPE_TABLET | BLUETOOTH_TYPE_JOYPAD)
+/**
+ * BLUETOOTH_TYPE_AUDIO:
+ *
+ * Use this value to select any Bluetooth audio device where a #BluetoothType enum is required.
+ */
 #define BLUETOOTH_TYPE_AUDIO (BLUETOOTH_TYPE_HEADSET | BLUETOOTH_TYPE_HEADPHONES | BLUETOOTH_TYPE_OTHER_AUDIO)
 
 /**
  * BluetoothColumn:
- * @BLUETOOTH_COLUMN_PROXY: a #DBusGProxy object
+ * @BLUETOOTH_COLUMN_PROXY: a #GDBusProxy object
+ * @BLUETOOTH_COLUMN_PROPERTIES: a #GDBusProxy object for DBus.Properties
  * @BLUETOOTH_COLUMN_ADDRESS: a string representing a Bluetooth address
  * @BLUETOOTH_COLUMN_ALIAS: a string to use for display (the name of the device, or its address if the name is not known). Only available for devices.
  * @BLUETOOTH_COLUMN_NAME: a string representing the device or adapter's name
@@ -121,6 +144,7 @@ typedef enum {
  **/
 typedef enum {
 	BLUETOOTH_COLUMN_PROXY,
+	BLUETOOTH_COLUMN_PROPERTIES,
 	BLUETOOTH_COLUMN_ADDRESS,
 	BLUETOOTH_COLUMN_ALIAS,
 	BLUETOOTH_COLUMN_NAME,
@@ -136,12 +160,12 @@ typedef enum {
 	BLUETOOTH_COLUMN_POWERED,
 	BLUETOOTH_COLUMN_SERVICES,
 	BLUETOOTH_COLUMN_UUIDS,
-	_BLUETOOTH_NUM_COLUMNS /*< skip >*/
 } BluetoothColumn;
 
+#define _BLUETOOTH_NUM_COLUMNS (BLUETOOTH_COLUMN_UUIDS + 1)
+
 /**
  * BluetoothStatus:
- *
  * @BLUETOOTH_STATUS_INVALID: whether the status has been set yet
  * @BLUETOOTH_STATUS_DISCONNECTED: whether the service is disconnected
  * @BLUETOOTH_STATUS_CONNECTED: whether the service is connected
diff --git a/lib/bluetooth-fdo.xml b/lib/bluetooth-fdo.xml
new file mode 100644
index 0000000..398d613
--- /dev/null
+++ b/lib/bluetooth-fdo.xml
@@ -0,0 +1,33 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node>
+  <interface name="org.freedesktop.DBus.ObjectManager">
+    <method name="GetManagedObjects"><arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
+    </method>
+    <signal name="InterfacesAdded"><arg name="object" type="o"/>
+      <arg name="interfaces" type="a{sa{sv}}"/>
+    </signal>
+    <signal name="InterfacesRemoved"><arg name="object" type="o"/>
+      <arg name="interfaces" type="as"/>
+    </signal>
+  </interface>
+
+  <interface name="org.freedesktop.DBus.Properties"><method name="Get"><arg name="interface" type="s" direction="in"/>
+      <arg name="name" type="s" direction="in"/>
+      <arg name="value" type="v" direction="out"/>
+    </method>
+    <method name="Set"><arg name="interface" type="s" direction="in"/>
+      <arg name="name" type="s" direction="in"/>
+      <arg name="value" type="v" direction="in"/>
+    </method>
+    <method name="GetAll"><arg name="interface" type="s" direction="in"/>
+      <arg name="properties" type="a{sv}" direction="out"/>
+    </method>
+    <signal name="PropertiesChanged"><arg name="interface" type="s"/>
+      <arg name="changed_properties" type="a{sv}"/>
+      <arg name="invalidated_properties" type="as"/>
+    </signal>
+  </interface>
+</node>
+
diff --git a/lib/bluetooth-filter-widget.c b/lib/bluetooth-filter-widget.c
index de2777e..1144615 100644
--- a/lib/bluetooth-filter-widget.c
+++ b/lib/bluetooth-filter-widget.c
@@ -31,6 +31,7 @@
 
 #include "bluetooth-filter-widget.h"
 #include "bluetooth-client.h"
+#include "bluetooth-utils.h"
 #include "mate-bluetooth-enum-types.h"
 
 #define BLUETOOTH_FILTER_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
diff --git a/lib/bluetooth-plugin-manager.c b/lib/bluetooth-plugin-manager.c
index f8a4a65..c3193b3 100644
--- a/lib/bluetooth-plugin-manager.c
+++ b/lib/bluetooth-plugin-manager.c
@@ -40,13 +40,9 @@
 #include "bluetooth-plugin-manager.h"
 
 #include "bluetooth-client.h"
+#include "bluetooth-utils.h"
 
-#define UNINSTALLED_PLUGINDIR "../lib/plugins"
-
-#define SOEXT           ("." G_MODULE_SUFFIX)
-#define SOEXT_LEN       (strlen (SOEXT))
-
-GList *plugin_list = NULL;
+static GList *plugin_list = NULL;
 
 static void
 bluetooth_plugin_dir_process (const char *plugindir)
@@ -65,7 +61,7 @@ bluetooth_plugin_dir_process (const char *plugindir)
 			g_error_free (err);
 	} else {
 		while ((item = g_dir_read_name(dir))) {
-			if (g_str_has_suffix (item, SOEXT)) {
+			if (g_str_has_suffix (item, "." G_MODULE_SUFFIX)) {
 				char *module_path;
 
 				p = g_new0(GbtPlugin, 1); 
@@ -86,7 +82,7 @@ bluetooth_plugin_dir_process (const char *plugindir)
 
 				gbt_init_plugin (p);
 
-				plugin_list = g_list_append (plugin_list, p); 
+				plugin_list = g_list_append (plugin_list, p);
 			}
 		}
 		g_dir_close (dir);
@@ -103,11 +99,6 @@ bluetooth_plugin_dir_process (const char *plugindir)
 gboolean
 bluetooth_plugin_manager_init (void)
 {
-	if (g_file_test (UNINSTALLED_PLUGINDIR, G_FILE_TEST_IS_DIR) != FALSE) {
-		/* Try to load the local plugins */
-		bluetooth_plugin_dir_process ("../lib/plugins/.libs/");
-	}
-
 	bluetooth_plugin_dir_process (PLUGINDIR);
 
 	return g_list_length (plugin_list) != 0;
@@ -138,12 +129,12 @@ bluetooth_plugin_manager_cleanup (void)
 /**
  * bluetooth_plugin_manager_get_widgets:
  * @bdaddr: a Bluetooth address representing a device
- * @uuids: an array of UUIDs supported by the device.
+ * @uuids: an array of UUIDs supported by the device
  *
  * Returns a list of widgets suitable for configuring the device
  * represented by @address, for the services listed in @uuids.
  *
- * Return value: a #GList of #GtkWidget, or %NULL is none.
+ * Return value: (element-type Gtk.Widget) (transfer none): a #GList of #GtkWidget, or %NULL if none.
  **/
 GList *
 bluetooth_plugin_manager_get_widgets (const char *bdaddr,
diff --git a/lib/bluetooth-plugin.h b/lib/bluetooth-plugin.h
index f24d115..ff32321 100644
--- a/lib/bluetooth-plugin.h
+++ b/lib/bluetooth-plugin.h
@@ -1,5 +1,5 @@
-#ifndef _MATE_BLUETOOTH_PLUGIN_H_
-#define _MATE_BLUETOOTH_PLUGIN_H_
+#ifndef _GNOME_BLUETOOTH_PLUGIN_H_
+#define _GNOME_BLUETOOTH_PLUGIN_H_
 
 #include <gmodule.h>
 #include <gtk/gtk.h>
@@ -23,7 +23,7 @@ typedef struct _GbtPlugin GbtPlugin;
  * @get_config_widgets: Returns the configuration widget for the passed Bluetooth address and UUIDs
  * @device_removed: Remove any configuration relating to the Bluetooth address passed
  *
- * A structure representing a mate-bluetooth wizard and properties plugin. You should also call GBT_INIT_PLUGIN() on the plugin structure to export it.
+ * A structure representing a gnome-bluetooth wizard and properties plugin. You should also call GBT_INIT_PLUGIN() on the plugin structure to export it.
  **/
 struct _GbtPluginInfo 
 {
@@ -38,7 +38,7 @@ struct _GbtPluginInfo
  * @module: the #GModule for the opened shared library
  * @info: a #GbtPluginInfo structure
  *
- * A structure as used in mate-bluetooth.
+ * A structure as used in gnome-bluetooth.
  **/
 struct _GbtPlugin
 {
@@ -50,7 +50,7 @@ struct _GbtPlugin
 * GBT_INIT_PLUGIN:
 * @plugininfo: a #GbtPluginInfo structure representing the plugin
 *
-* Call this on an #GbtPluginInfo structure to make it available to mate-bluetooth.
+* Call this on an #GbtPluginInfo structure to make it available to gnome-bluetooth.
 **/
 #define GBT_INIT_PLUGIN(plugininfo)					\
 	gboolean gbt_init_plugin (GbtPlugin *plugin);			\
@@ -60,5 +60,5 @@ struct _GbtPlugin
 		return TRUE;						\
 	}
 
-#endif /* _MATE_BLUETOOTH_PLUGIN_H_ */
+#endif /* _GNOME_BLUETOOTH_PLUGIN_H_ */
 
diff --git a/lib/bluetooth-utils.c b/lib/bluetooth-utils.c
new file mode 100644
index 0000000..08b8caf
--- /dev/null
+++ b/lib/bluetooth-utils.c
@@ -0,0 +1,362 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2011  Bastien Nocera <hadess@hadess.net>
+ *  Copyright (C) 2010       Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/**
+ * SECTION:bluetooth-utils
+ * @short_description: Bluetooth utility functions
+ * @stability: Stable
+ * @include: bluetooth-utils.h
+ *
+ * Those helper functions are used throughout the Bluetooth
+ * management utilities.
+ **/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include "bluetooth-utils.h"
+#include "mate-bluetooth-enum-types.h"
+
+/**
+ * bluetooth_type_to_string:
+ * @type: a #BluetoothType
+ *
+ * Returns a human-readable string representation of @type usable for display to users. Do not free the return value.
+ * The returned string is already translated with gettext().
+ *
+ * Return value: a string.
+ **/
+const gchar *
+bluetooth_type_to_string (BluetoothType type)
+{
+	switch (type) {
+	case BLUETOOTH_TYPE_ANY:
+		return _("All types");
+	case BLUETOOTH_TYPE_PHONE:
+		return _("Phone");
+	case BLUETOOTH_TYPE_MODEM:
+		return _("Modem");
+	case BLUETOOTH_TYPE_COMPUTER:
+		return _("Computer");
+	case BLUETOOTH_TYPE_NETWORK:
+		return _("Network");
+	case BLUETOOTH_TYPE_HEADSET:
+		/* translators: a hands-free headset, a combination of a single speaker with a microphone */
+		return _("Headset");
+	case BLUETOOTH_TYPE_HEADPHONES:
+		return _("Headphones");
+	case BLUETOOTH_TYPE_OTHER_AUDIO:
+		return _("Audio device");
+	case BLUETOOTH_TYPE_KEYBOARD:
+		return _("Keyboard");
+	case BLUETOOTH_TYPE_MOUSE:
+		return _("Mouse");
+	case BLUETOOTH_TYPE_CAMERA:
+		return _("Camera");
+	case BLUETOOTH_TYPE_PRINTER:
+		return _("Printer");
+	case BLUETOOTH_TYPE_JOYPAD:
+		return _("Joypad");
+	case BLUETOOTH_TYPE_TABLET:
+		return _("Tablet");
+	case BLUETOOTH_TYPE_VIDEO:
+		return _("Video device");
+	case BLUETOOTH_TYPE_REMOTE_CONTROL:
+		return _("Remote control");
+	case BLUETOOTH_TYPE_SCANNER:
+		return _("Scanner");
+	case BLUETOOTH_TYPE_DISPLAY:
+		return _("Display");
+	case BLUETOOTH_TYPE_WEARABLE:
+		return _("Wearable");
+	case BLUETOOTH_TYPE_TOY:
+		return _("Toy");
+	}
+
+	return _("Unknown");
+}
+
+/**
+ * bluetooth_verify_address:
+ * @bdaddr: a string representing a Bluetooth address
+ *
+ * Returns whether the string is a valid Bluetooth address. This does not contact the device in any way.
+ *
+ * Return value: %TRUE if the address is valid, %FALSE if not.
+ **/
+gboolean
+bluetooth_verify_address (const char *bdaddr)
+{
+	guint i;
+
+	g_return_val_if_fail (bdaddr != NULL, FALSE);
+
+	if (strlen (bdaddr) != 17)
+		return FALSE;
+
+	for (i = 0; i < 17; i++) {
+		if (((i + 1) % 3) == 0) {
+			if (bdaddr[i] != ':')
+				return FALSE;
+			continue;
+		}
+		if (g_ascii_isxdigit (bdaddr[i]) == FALSE)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+/**
+ * bluetooth_class_to_type:
+ * @class: a Bluetooth device class
+ *
+ * Returns the type of device corresponding to the given @class value.
+ *
+ * Return value: a #BluetoothType.
+ **/
+BluetoothType
+bluetooth_class_to_type (guint32 class)
+{
+	switch ((class & 0x1f00) >> 8) {
+	case 0x01:
+		return BLUETOOTH_TYPE_COMPUTER;
+	case 0x02:
+		switch ((class & 0xfc) >> 2) {
+		case 0x01:
+		case 0x02:
+		case 0x03:
+		case 0x05:
+			return BLUETOOTH_TYPE_PHONE;
+		case 0x04:
+			return BLUETOOTH_TYPE_MODEM;
+		}
+		break;
+	case 0x03:
+		return BLUETOOTH_TYPE_NETWORK;
+	case 0x04:
+		switch ((class & 0xfc) >> 2) {
+		case 0x01:
+		case 0x02:
+			return BLUETOOTH_TYPE_HEADSET;
+		case 0x06:
+			return BLUETOOTH_TYPE_HEADPHONES;
+		case 0x0b: /* VCR */
+		case 0x0c: /* Video Camera */
+		case 0x0d: /* Camcorder */
+			return BLUETOOTH_TYPE_VIDEO;
+		default:
+			return BLUETOOTH_TYPE_OTHER_AUDIO;
+		}
+		break;
+	case 0x05:
+		switch ((class & 0xc0) >> 6) {
+		case 0x00:
+			switch ((class & 0x1e) >> 2) {
+			case 0x01:
+			case 0x02:
+				return BLUETOOTH_TYPE_JOYPAD;
+			case 0x03:
+				return BLUETOOTH_TYPE_REMOTE_CONTROL;
+			}
+			break;
+		case 0x01:
+			return BLUETOOTH_TYPE_KEYBOARD;
+		case 0x02:
+			switch ((class & 0x1e) >> 2) {
+			case 0x05:
+				return BLUETOOTH_TYPE_TABLET;
+			default:
+				return BLUETOOTH_TYPE_MOUSE;
+			}
+		}
+		break;
+	case 0x06:
+		if (class & 0x80)
+			return BLUETOOTH_TYPE_PRINTER;
+		if (class & 0x40)
+			return BLUETOOTH_TYPE_SCANNER;
+		if (class & 0x20)
+			return BLUETOOTH_TYPE_CAMERA;
+		if (class & 0x10)
+			return BLUETOOTH_TYPE_DISPLAY;
+		break;
+	case 0x07:
+		return BLUETOOTH_TYPE_WEARABLE;
+	case 0x08:
+		return BLUETOOTH_TYPE_TOY;
+	}
+
+	return 0;
+}
+
+static const char *
+uuid16_custom_to_string (guint uuid16, const char *uuid)
+{
+	switch (uuid16) {
+	case 0x2:
+		return "SyncMLClient";
+	case 0x5601:
+		return "Nokia SyncML Server";
+	default:
+		g_debug ("Unhandled custom UUID %s (0x%x)", uuid, uuid16);
+		return NULL;
+	}
+}
+
+/* Short names from Table 2 at:
+ * https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm */
+static const char *
+uuid16_to_string (guint uuid16, const char *uuid)
+{
+	switch (uuid16) {
+	case BLUETOOTH_UUID_SPP:
+		return "SerialPort";
+	case BLUETOOTH_UUID_DUN:
+		return "DialupNetworking";
+	case BLUETOOTH_UUID_IRMC:
+		return "IrMCSync";
+	case BLUETOOTH_UUID_OPP:
+		return "OBEXObjectPush";
+	case BLUETOOTH_UUID_FTP:
+		return "OBEXFileTransfer";
+	case BLUETOOTH_UUID_HSP:
+		return "HSP";
+	case BLUETOOTH_UUID_A2DP_SOURCE:
+		return "AudioSource";
+	case BLUETOOTH_UUID_A2DP_SINK:
+		return "AudioSink";
+	case BLUETOOTH_UUID_AVRCP_TARGET:
+		return "A/V_RemoteControlTarget";
+	case BLUETOOTH_UUID_AVRCP_CONTROL:
+		return "A/V_RemoteControl";
+	case BLUETOOTH_UUID_HSP_AG:
+		return "Headset_-_AG";
+	case BLUETOOTH_UUID_PAN_PANU:
+		return "PANU";
+	case BLUETOOTH_UUID_PAN_NAP:
+		return "NAP";
+	case BLUETOOTH_UUID_PAN_GN:
+		return "GN";
+	case BLUETOOTH_UUID_HFP_HF:
+		return "Handsfree";
+	case BLUETOOTH_UUID_HFP_AG:
+		return "HandsfreeAudioGateway";
+	case BLUETOOTH_UUID_HID:
+		return "HumanInterfaceDeviceService";
+	case BLUETOOTH_UUID_SAP:
+		return "SIM_Access";
+	case BLUETOOTH_UUID_PBAP:
+		return "Phonebook_Access_-_PSE";
+	case BLUETOOTH_UUID_GENERIC_AUDIO:
+		return "GenericAudio";
+	case BLUETOOTH_UUID_SDP: /* ServiceDiscoveryServerServiceClassID */
+	case BLUETOOTH_UUID_PNP: /* PnPInformation */
+		/* Those are ignored */
+		return NULL;
+	case BLUETOOTH_UUID_GENERIC_NET:
+		return "GenericNetworking";
+	case BLUETOOTH_UUID_VDP_SOURCE:
+		return "VideoSource";
+	case 0x8e771303:
+	case 0x8e771301:
+		return "SEMC HLA";
+	case 0x8e771401:
+		return "SEMC Watch Phone";
+	default:
+		g_debug ("Unhandled UUID %s (0x%x)", uuid, uuid16);
+		return NULL;
+	}
+}
+
+/**
+ * bluetooth_uuid_to_string:
+ * @uuid: a string representing a Bluetooth UUID
+ *
+ * Returns a string representing a human-readable (but not usable for display to users) version of the @uuid. Do not free the return value.
+ *
+ * Return value: a string.
+ **/
+const char *
+bluetooth_uuid_to_string (const char *uuid)
+{
+	char **parts;
+	guint uuid16;
+	gboolean is_custom = FALSE;
+
+	if (g_str_has_suffix (uuid, "-0000-1000-8000-0002ee000002") != FALSE)
+		is_custom = TRUE;
+
+	parts = g_strsplit (uuid, "-", -1);
+	if (parts == NULL || parts[0] == NULL) {
+		g_strfreev (parts);
+		return NULL;
+	}
+
+	uuid16 = g_ascii_strtoull (parts[0], NULL, 16);
+	g_strfreev (parts);
+	if (uuid16 == 0)
+		return NULL;
+
+	if (is_custom == FALSE)
+		return uuid16_to_string (uuid16, uuid);
+	return uuid16_custom_to_string (uuid16, uuid);
+}
+
+/**
+ * bluetooth_send_to_address:
+ * @address: Remote device to use
+ * @alias: Remote device's name
+ *
+ * Start a GUI application for transfering files over Bluetooth.
+ **/
+void
+bluetooth_send_to_address (const char *address,
+			   const char *alias)
+{
+	GPtrArray *a;
+	GError *err = NULL;
+
+	a = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+
+	g_ptr_array_add (a, g_strdup ("bluetooth-sendto"));
+	if (address != NULL)
+		g_ptr_array_add (a, g_strdup_printf ("--device=%s", address));
+	if (address != NULL && alias != NULL)
+		g_ptr_array_add (a, g_strdup_printf ("--name=%s", alias));
+	g_ptr_array_add (a, NULL);
+
+	if (g_spawn_async(NULL, (char **) a->pdata, NULL,
+			  G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err) == FALSE) {
+		g_printerr("Couldn't execute command: %s\n", err->message);
+		g_error_free (err);
+	}
+
+	g_ptr_array_free (a, TRUE);
+}
+
diff --git a/lib/bluetooth-utils.h b/lib/bluetooth-utils.h
new file mode 100644
index 0000000..41bb2c2
--- /dev/null
+++ b/lib/bluetooth-utils.h
@@ -0,0 +1,72 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2011  Bastien Nocera <hadess@hadess.net>
+ *  Copyright (C) 2010       Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __BLUETOOTH_UTILS_H
+#define __BLUETOOTH_UTILS_H
+
+#include <gio/gio.h>
+#include <bluetooth-enums.h>
+
+G_BEGIN_DECLS
+
+/*
+ * The profile UUID list is provided by the Bluetooth SIG:
+ * https://www.bluetooth.org/en-us/specification/assigned-numbers-overview/service-discovery
+ */
+#define BLUETOOTH_UUID_SPP		0x1101
+#define BLUETOOTH_UUID_DUN		0x1103
+#define BLUETOOTH_UUID_IRMC		0x1104
+#define BLUETOOTH_UUID_OPP		0x1105
+#define BLUETOOTH_UUID_FTP		0x1106
+#define BLUETOOTH_UUID_HSP		0x1108
+#define BLUETOOTH_UUID_A2DP_SOURCE	0x110A
+#define BLUETOOTH_UUID_A2DP_SINK	0x110B
+#define BLUETOOTH_UUID_AVRCP_TARGET	0x110C
+#define BLUETOOTH_UUID_AVRCP_CONTROL	0x110E
+#define BLUETOOTH_UUID_HSP_AG		0x1112
+#define BLUETOOTH_UUID_PAN_PANU		0x1115
+#define BLUETOOTH_UUID_PAN_NAP		0x1116
+#define BLUETOOTH_UUID_PAN_GN		0x1117
+#define BLUETOOTH_UUID_HFP_HF		0x111E
+#define BLUETOOTH_UUID_HFP_AG		0x111F
+#define BLUETOOTH_UUID_HID		0x1124
+#define BLUETOOTH_UUID_SAP		0x112d
+#define BLUETOOTH_UUID_PBAP		0x112F
+#define BLUETOOTH_UUID_GENERIC_AUDIO	0x1203
+#define BLUETOOTH_UUID_SDP		0x1000
+#define BLUETOOTH_UUID_PNP		0x1200
+#define BLUETOOTH_UUID_GENERIC_NET	0x1201
+#define BLUETOOTH_UUID_VDP_SOURCE	0x1303
+
+BluetoothType  bluetooth_class_to_type  (guint32 class);
+const gchar   *bluetooth_type_to_string (guint type);
+gboolean       bluetooth_verify_address (const char *bdaddr);
+const char    *bluetooth_uuid_to_string (const char *uuid);
+
+void bluetooth_send_to_address (const char *address,
+				const char *alias);
+
+G_END_DECLS
+
+#endif /* __BLUETOOTH_UTILS_H */
diff --git a/lib/marshal.list b/lib/marshal.list
deleted file mode 100644
index bc7f458..0000000
--- a/lib/marshal.list
+++ /dev/null
@@ -1,6 +0,0 @@
-VOID:STRING,BOXED
-
-VOID:STRING,STRING
-VOID:STRING,STRING,UINT64
-VOID:UINT64
-VOID:STRING,STRING,STRING
diff --git a/lib/mate-bluetooth.symbols b/lib/mate-bluetooth.symbols
index a5b1e9e..545d041 100644
--- a/lib/mate-bluetooth.symbols
+++ b/lib/mate-bluetooth.symbols
@@ -1,3 +1,4 @@
+bluetooth_chooser_dump_selected_device
 bluetooth_chooser_get_type
 bluetooth_chooser_new
 bluetooth_chooser_set_title
@@ -8,31 +9,68 @@ bluetooth_chooser_get_selected_device_icon
 bluetooth_chooser_get_selected_device_type
 bluetooth_chooser_get_selected_device_is_connected
 bluetooth_chooser_get_model
-bluetooth_chooser_get_type_column
 bluetooth_chooser_get_treeview
+bluetooth_chooser_get_scrolled_window
+bluetooth_chooser_remove_selected_device
 bluetooth_chooser_start_discovery
 bluetooth_chooser_stop_discovery
-bluetooth_client_set_discoverable
-bluetooth_chooser_remove_selected_device
 bluetooth_chooser_button_get_type
 bluetooth_chooser_button_new
 bluetooth_chooser_button_available
+bluetooth_client_setup_device
+bluetooth_client_setup_device_finish
+bluetooth_client_dump_device
 bluetooth_client_get_type
 bluetooth_client_new
 bluetooth_client_get_model
 bluetooth_client_get_filter_model
 bluetooth_client_get_adapter_model
 bluetooth_client_get_device_model
-bluetooth_client_get_device_filter_model
+bluetooth_client_connect_service
+bluetooth_client_connect_service_finish
+bluetooth_client_set_trusted
+bluetooth_client_get_device
+bluetooth_class_to_type
 bluetooth_type_to_string
 bluetooth_verify_address
 bluetooth_uuid_to_string
+bluetooth_send_to_address
 bluetooth_column_get_type
 bluetooth_category_get_type
 bluetooth_type_get_type
+bluetooth_status_get_type
 bluetooth_filter_widget_new
 bluetooth_filter_widget_set_title
 bluetooth_filter_widget_get_type
 bluetooth_filter_widget_bind_filter
 bluetooth_chooser_combo_get_type
 bluetooth_chooser_combo_new
+bluetooth_plugin_manager_init
+bluetooth_plugin_manager_cleanup
+bluetooth_plugin_manager_get_widgets
+bluetooth_plugin_manager_device_deleted
+bluetooth_killswitch_get_type
+bluetooth_killswitch_new
+bluetooth_killswitch_has_killswitches
+bluetooth_killswitch_set_state
+bluetooth_killswitch_get_state
+bluetooth_agent_new
+bluetooth_agent_set_pincode_func
+bluetooth_agent_register
+bluetooth_agent_unregister
+bluetooth_agent_set_confirm_func
+bluetooth_agent_set_passkey_func
+bluetooth_agent_set_cancel_func
+bluetooth_agent_error_quark
+bluetooth_agent_set_authorize_func
+bluetooth_agent_set_display_func
+bluetooth_agent_set_display_pincode_func
+bluetooth_agent_set_authorize_service_func
+bluetooth_agent_setup
+bluetooth_settings_widget_get_type
+bluetooth_settings_widget_new
+bluetooth_pairing_dialog_new
+bluetooth_pairing_dialog_get_type
+bluetooth_pairing_dialog_set_mode
+bluetooth_pairing_dialog_get_mode
+bluetooth_pairing_dialog_set_pin_entered
diff --git a/lib/obex-agent.c b/lib/obex-agent.c
deleted file mode 100644
index b53c2cc..0000000
--- a/lib/obex-agent.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include "obex-agent.h"
-
-#ifdef DEBUG
-#define DBG(fmt, arg...) printf("%s:%s() " fmt "\n", __FILE__, __FUNCTION__ , ## arg)
-#else
-#define DBG(fmt...)
-#endif
-
-#define OBEX_SERVICE	"org.openobex.client"
-
-#define OBEX_CLIENT_PATH	"/"
-#define OBEX_CLIENT_INTERFACE	"org.openobex.Client"
-#define OBEX_TRANSFER_INTERFACE	"org.openobex.Transfer"
-
-static DBusGConnection *connection = NULL;
-
-#define OBEX_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
-					OBEX_TYPE_AGENT, ObexAgentPrivate))
-
-typedef struct _ObexAgentPrivate ObexAgentPrivate;
-
-struct _ObexAgentPrivate {
-	gchar *busname;
-	gchar *path;
-
-	ObexAgentReleaseFunc release_func;
-	gpointer release_data;
-
-	ObexAgentRequestFunc request_func;
-	gpointer request_data;
-
-	ObexAgentProgressFunc progress_func;
-	gpointer progress_data;
-
-	ObexAgentCompleteFunc complete_func;
-	gpointer complete_data;
-
-	ObexAgentErrorFunc error_func;
-	gpointer error_data;
-};
-
-G_DEFINE_TYPE(ObexAgent, obex_agent, G_TYPE_OBJECT)
-
-static gboolean obex_agent_request(ObexAgent *agent, const char *path,
-						DBusGMethodInvocation *context)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
-
-	if (priv->busname == NULL) {
-		/* When we get called the first time, if OBEX_SERVICE
-		 * was not available, we get its name here */
-		priv->busname = sender;
-	} else {
-		if (g_str_equal(sender, priv->busname) == FALSE) {
-			g_free (sender);
-			return FALSE;
-		}
-
-		g_free (sender);
-	}
-
-	if (priv->request_func) {
-		DBusGProxy *proxy;
-
-		proxy = dbus_g_proxy_new_for_name(connection, OBEX_SERVICE,
-						path, OBEX_TRANSFER_INTERFACE);
-
-		//FIXME check result
-		result = priv->request_func(context, proxy,
-						priv->request_data);
-
-		g_object_unref(proxy);
-	} else
-		dbus_g_method_return(context, "");
-
-	return TRUE;
-}
-
-static gboolean obex_agent_progress(ObexAgent *agent, const char *path,
-			guint64 transferred, DBusGMethodInvocation *context)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
-
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
-		return FALSE;
-	}
-
-	g_free (sender);
-
-	if (priv->progress_func) {
-		DBusGProxy *proxy;
-
-		proxy = dbus_g_proxy_new_for_name(connection, OBEX_SERVICE,
-						path, OBEX_TRANSFER_INTERFACE);
-
-		result = priv->progress_func(context, proxy, transferred,
-							priv->progress_data);
-
-		g_object_unref(proxy);
-	} else
-		dbus_g_method_return(context);
-
-	return result;
-}
-
-static gboolean obex_agent_complete(ObexAgent *agent, const char *path,
-						DBusGMethodInvocation *context)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
-
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
-		return FALSE;
-	}
-
-	g_free (sender);
-
-	if (priv->complete_func) {
-		DBusGProxy *proxy;
-
-		proxy = dbus_g_proxy_new_for_name(connection, OBEX_SERVICE,
-						path, OBEX_TRANSFER_INTERFACE);
-
-		result = priv->complete_func(context, proxy,
-						priv->complete_data);
-
-		g_object_unref(proxy);
-	} else
-		dbus_g_method_return(context);
-
-	return result;
-}
-
-static gboolean obex_agent_release(ObexAgent *agent,
-						DBusGMethodInvocation *context)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
-
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
-		return FALSE;
-	}
-
-	g_free (sender);
-
-	if (priv->release_func)
-		result = priv->release_func(context, priv->release_data);
-	else
-		dbus_g_method_return(context);
-
-	g_object_unref(agent);
-
-	return result;
-}
-
-static gboolean obex_agent_error(ObexAgent *agent,
-				 const char *path,
-				 const char *message,
-				 DBusGMethodInvocation *context)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-	char *sender = dbus_g_method_get_sender(context);
-	gboolean result = FALSE;
-
-	DBG("agent %p sender %s", agent, sender);
-
-	if (g_str_equal(sender, priv->busname) == FALSE) {
-		g_free (sender);
-		return FALSE;
-	}
-
-	g_free (sender);
-
-	if (priv->error_func) {
-		DBusGProxy *proxy;
-
-		proxy = dbus_g_proxy_new_for_name(connection, OBEX_SERVICE,
-						path, OBEX_TRANSFER_INTERFACE);
-
-		result = priv->error_func(context, proxy, message,
-							priv->progress_data);
-
-		g_object_unref(proxy);
-	} else
-		dbus_g_method_return(context);
-
-	return result;
-}
-
-#include "obex-agent-glue.h"
-
-static void obex_agent_init(ObexAgent *agent)
-{
-	DBG("agent %p", agent);
-}
-
-static void obex_agent_finalize(GObject *agent)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-
-	DBG("agent %p", agent);
-
-	g_free(priv->path);
-	g_free(priv->busname);
-
-	G_OBJECT_CLASS(obex_agent_parent_class)->finalize(agent);
-}
-
-static void obex_agent_class_init(ObexAgentClass *klass)
-{
-	GObjectClass *object_class = (GObjectClass *) klass;
-	GError *error = NULL;
-
-	DBG("class %p", klass);
-
-	g_type_class_add_private(klass, sizeof(ObexAgentPrivate));
-
-	object_class->finalize = obex_agent_finalize;
-
-	connection = 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);
-	}
-
-	dbus_g_object_type_install_info(OBEX_TYPE_AGENT,
-					&dbus_glib_obex_agent_object_info);
-
-	//dbus_g_error_domain_register(AGENT_ERROR, "org.openobex.Error",
-	//						AGENT_ERROR_TYPE);
-}
-
-ObexAgent *obex_agent_new(void)
-{
-	ObexAgent *agent;
-
-	agent = OBEX_AGENT(g_object_new(OBEX_TYPE_AGENT, NULL));
-
-	DBG("agent %p", agent);
-
-	return agent;
-}
-
-gboolean obex_agent_setup(ObexAgent *agent, const char *path)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-	DBusGProxy *proxy;
-	GObject *object;
-
-	DBG("agent %p path %s", agent, path);
-
-	if (priv->path != NULL)
-		return FALSE;
-
-	priv->path = g_strdup(path);
-
-	proxy = dbus_g_proxy_new_for_name_owner(connection, OBEX_SERVICE,
-			OBEX_CLIENT_PATH, OBEX_CLIENT_INTERFACE, NULL);
-
-	g_free(priv->busname);
-
-	if (proxy != NULL) {
-		priv->busname = g_strdup(dbus_g_proxy_get_bus_name(proxy));
-		g_object_unref(proxy);
-	} else
-		priv->busname = NULL;
-
-	object = dbus_g_connection_lookup_g_object(connection, priv->path);
-	if (object != NULL)
-		g_object_unref(object);
-
-	dbus_g_connection_register_g_object(connection,
-						priv->path, G_OBJECT(agent));
-
-	return TRUE;
-}
-
-void obex_agent_set_release_func(ObexAgent *agent,
-				ObexAgentReleaseFunc func, gpointer data)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-
-	DBG("agent %p", agent);
-
-	priv->release_func = func;
-	priv->release_data = data;
-}
-
-void obex_agent_set_request_func(ObexAgent *agent,
-				ObexAgentRequestFunc func, gpointer data)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-
-	DBG("agent %p", agent);
-
-	priv->request_func = func;
-	priv->request_data = data;
-}
-
-void obex_agent_set_progress_func(ObexAgent *agent,
-				ObexAgentProgressFunc func, gpointer data)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-
-	DBG("agent %p", agent);
-
-	priv->progress_func = func;
-	priv->progress_data = data;
-}
-
-void obex_agent_set_complete_func(ObexAgent *agent,
-				ObexAgentCompleteFunc func, gpointer data)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-
-	DBG("agent %p", agent);
-
-	priv->complete_func = func;
-	priv->complete_data = data;
-}
-
-void obex_agent_set_error_func(ObexAgent *agent,
-			       ObexAgentErrorFunc func, gpointer data)
-{
-	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
-
-	DBG("agent %p", agent);
-
-	priv->error_func = func;
-	priv->error_data = data;
-}
diff --git a/lib/obex-agent.h b/lib/obex-agent.h
deleted file mode 100644
index fbdb6bd..0000000
--- a/lib/obex-agent.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef __OBEX_AGENT_H
-#define __OBEX_AGENT_H
-
-#include <glib-object.h>
-#include <dbus/dbus-glib.h>
-
-G_BEGIN_DECLS
-
-#define OBEX_TYPE_AGENT (obex_agent_get_type())
-#define OBEX_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
-						OBEX_TYPE_AGENT, ObexAgent))
-#define OBEX_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
-					OBEX_TYPE_AGENT, ObexAgentClass))
-#define OBEX_IS_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
-							OBEX_TYPE_AGENT))
-#define OBEX_IS_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \
-							OBEX_TYPE_AGENT))
-#define OBEX_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
-					OBEX_TYPE_AGENT, ObexAgentClass))
-
-typedef struct _ObexAgent ObexAgent;
-typedef struct _ObexAgentClass ObexAgentClass;
-
-struct _ObexAgent {
-	GObject parent;
-};
-
-struct _ObexAgentClass {
-	GObjectClass parent_class;
-};
-
-GType obex_agent_get_type(void);
-
-ObexAgent *obex_agent_new(void);
-
-gboolean obex_agent_setup(ObexAgent *agent, const char *path);
-
-typedef gboolean (*ObexAgentReleaseFunc) (DBusGMethodInvocation *context,
-								gpointer data);
-typedef gboolean (*ObexAgentRequestFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *transfer, gpointer data);
-typedef gboolean (*ObexAgentProgressFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *transfer,
-					guint64 transferred, gpointer data);
-typedef gboolean (*ObexAgentCompleteFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *transfer, gpointer data);
-typedef gboolean (*ObexAgentErrorFunc) (DBusGMethodInvocation *context,
-					DBusGProxy *transfer,
-					const char *message,
-					gpointer data);
-
-void obex_agent_set_release_func(ObexAgent *agent,
-				ObexAgentReleaseFunc func, gpointer data);
-void obex_agent_set_request_func(ObexAgent *agent,
-				ObexAgentRequestFunc func, gpointer data);
-void obex_agent_set_progress_func(ObexAgent *agent,
-				ObexAgentProgressFunc func, gpointer data);
-void obex_agent_set_complete_func(ObexAgent *agent,
-				ObexAgentCompleteFunc func, gpointer data);
-void obex_agent_set_error_func(ObexAgent *agent,
-			       ObexAgentErrorFunc func, gpointer data);
-G_END_DECLS
-
-#endif /* __OBEX_AGENT_H */
diff --git a/lib/obex-agent.xml b/lib/obex-agent.xml
deleted file mode 100644
index 082ca95..0000000
--- a/lib/obex-agent.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/">
-  <interface name="org.openobex.Agent">
-    <method name="Request">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="transfer"/>
-      <arg type="s" name="name" direction="out"/>
-    </method>
-
-    <method name="Progress">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="transfer"/>
-      <arg type="t" name="transferred"/>
-    </method>
-
-    <method name="Complete">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="transfer"/>
-    </method>
-
-    <method name="Release">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-    </method>
-
-    <method name="Error">
-      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-      <arg type="o" name="transfer"/>
-      <arg type="s" name="message"/>
-    </method>
-  </interface>
-</node>
diff --git a/lib/pin-code-database.xml b/lib/pin-code-database.xml
new file mode 100644
index 0000000..ed556d3
--- /dev/null
+++ b/lib/pin-code-database.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This is a PIN code database for use in the Bluetooth wizard.
+
+  Copyright (C) 2008-2009  Bastien Nocera <hadess@hadess.net>
+
+  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+-->
+
+<!--
+  The wizard will match devices, following the order of the XML file [1],
+  on any combination of type, OUI, or name. The name is matched through a
+  sub-string search (it should contain the name mentioned in this file if any).
+
+  The special NULL pin means that the devices will not be paired, but
+  connected to and marked as trusted. This is for devices such as mice
+  and joypads where there is no encryption
+
+  The special "KEYBOARD" pin means that the device needs a specific handling
+  in the UI (in this case, needs to mention the necessity to type "Enter" after
+  entering the PIN).
+
+  If a device can use a random PIN but is limited in the number of digits that
+  can be entered, then set the "pin" attribute should be set to "max:X" where X
+  is the maximum number of digits, for example max:4 for 4 digits.
+
+  [1]: So specific devices should be at the top, and generic ones at the bottom,
+  so settings for specific devices are overridden as expected.
+-->
+
+<!DOCTYPE devices [
+	<!ELEMENT devices (device)+>
+	<!ELEMENT device EMPTY>
+	<!ATTLIST device type (any|mouse|tablet|keyboard|headset|headphones|audio|printer|network) "any">
+	<!ATTLIST device oui CDATA #IMPLIED>
+	<!ATTLIST device vendor CDATA #IMPLIED>
+	<!ATTLIST device name CDATA #IMPLIED>
+	<!ATTLIST device pin CDATA #REQUIRED>
+]>
+
+<devices>
+
+<!-- Input devices -->
+
+	<!-- TomTom Go remote -->
+	<device type="keyboard" oui="00:13:6C:" name="TomTom Remote" pin="0000"/>
+
+	<!-- Sony PlayStation 3 Remote Control
+	     with a OUI from Alps Electric -->
+	<device vendor="alps" name="BD Remote Control" pin="NULL"/>
+
+	<!-- Apple Wireless and Mighty Mouse
+	     Note: Apple doesn't follow the specs, and requires their mice
+	     to be paired -->
+	<device vendor="apple" type="mouse" pin="0000"/>
+
+	<!-- Apple Magic Trackpad
+	     Note: same as above, tablet needs to be paired -->
+	<device vendor="apple" type="tablet" pin="0000"/>
+
+	<!-- Microsoft mice
+	     Again, same as above -->
+	<device oui="7C:1E:52:" type="mouse" name="Microsoft Wedge Touch Mouse" pin="0000"/>
+	<device oui="00:1D:D8:" type="mouse" name="Microsoft Wireless Notebook Presenter Mouse 8000" pin="0000"/>
+
+	<!-- BT-GPS8 JENTRO, GPS mouse -->
+	<device oui="00:0D:B5:" name="BT-GPS8 JENTRO" pin="0000"/>
+
+	<!-- Lenovo Ideacenter remote -->
+	<device oui="00:08:1B:" name="lenovo_RC" pin="0000"/>
+
+	<!-- ION iCade Game Controller -->
+	<device name="iCade" type="keyboard" pin="ICADE"/>
+
+<!-- GPS devices -->
+	<device oui="00:0D:B5:" name="TomTom Wireless GPS MkII" pin="0000"/>
+	<device oui="00:0D:B5:" name="GPS-GW-005" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560870 -->
+	<device oui="00:0A:3A:" name="BT GPS" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560606 -->
+	<device oui="00:1B:C1:" name="HOLUX_M-241" pin="0000"/>
+	<device oui="00:01:C1:" name="HOLUX_M-241" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560713 -->
+	<device oui="00:0B:24:" name="Triceiver" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560715 -->
+	<device oui="00:00:00:" name="BT-Q880" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560625 -->
+	<device oui="00:11:67:" name="eGPS-397" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560604 -->
+	<device oui="00:1B:C1:" name="HOLUX_M-1000" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=561326 -->
+	<device oui="00:0B:0D:" name="G-Rays1" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=571119 -->
+	<device oui="00:0B:0D:" name="G-Rays2" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=561327 -->
+	<device oui="00:0A:3A:" name="HUDGPS" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=562479 -->
+	<device oui="00:0B:0D:" name="iBT-GPS" pin="0000"/>
+	<device oui="00:1C:88:" name="iBT-GPS" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=563554 -->
+	<device oui="00:0D:B5:" name="BT-GPS-37A4C2" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=563614 -->
+	<device oui="00:0B:0D:" name="HOLUX GPSlim240" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=563554 -->
+	<device oui="00:0D:B5:" name="BT-GPS-37A4C2" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=576490 -->
+	<device oui="00:0D:B5:" name="BT-GPS-339D35" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560315#c20 -->
+	<device oui="00:02:5B:" name="Pharos iGPS-BT" pin="12345678"/>
+
+	<!-- https://bugzilla.redhat.com/show_bug.cgi?id=472686#c0 -->
+	<device oui="00:00:00:" name="Rikaline" pin="0000"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560609 -->
+	<device oui="00:18:96:" name="GW-GPS-009" pin="0000"/>
+
+	<!-- https://bugzilla.gnome.org/show_bug.cgi?id=613698 -->
+	<device oui="00:0C:A5:" name="NAVMAN GPS ONE" pin="NAVMAN"/>
+
+<!-- Audio devices -->
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=560315 -->
+	<device type="headset" name="X3 micro" pin="1234"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=561324 -->
+	<device type="headset" oui="00:03:C9:" name="BT Headset" pin="1111"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=573059 -->
+	<device type="headset" oui="00:12:A1:" name="BT Stereo Headset" pin="1234"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=561325 -->
+	<device type="network" oui="00:06:66:" name="OBDPros scantool" pin="1234"/>
+
+	<!-- http://bugzilla.gnome.org/show_bug.cgi?id=583651 -->
+	<device type="audio" oui="00:1A:80:" name="CMT-DH5BT" pin="max:4"/>
+
+<!-- Generic types -->
+
+	<!-- Printers -->
+	<device type="printer" pin="0000"/>
+
+	<!-- Headphones and headsets -->
+	<device type="headphones" pin="0000"/>
+	<device type="headset" pin="0000"/>
+	<device type="audio" pin="0000"/>
+
+	<!-- Keyboard need a special help text -->
+	<device type="keyboard" pin="KEYBOARD"/>
+
+</devices>
diff --git a/lib/pin.c b/lib/pin.c
new file mode 100644
index 0000000..61e87ab
--- /dev/null
+++ b/lib/pin.c
@@ -0,0 +1,236 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009  Bastien Nocera <hadess@hadess.net>
+ *
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <libudev.h>
+#include <bluetooth-enums.h>
+#include <bluetooth-utils.h>
+
+#include "pin.h"
+
+#define PIN_CODE_DB "pin-code-database.xml"
+#define MAX_DIGITS_PIN_PREFIX "max:"
+
+char *
+oui_to_vendor (const char *oui)
+{
+	struct udev *udev;
+	struct udev_hwdb *hwdb;
+	struct udev_list_entry *list, *l;
+	char *modalias;
+	char *vendor = NULL;
+
+	if (oui == NULL ||
+	    strlen (oui) < 8)
+		return NULL;
+
+	udev = udev_new ();
+	if (udev == NULL)
+		goto bail;
+
+	hwdb = udev_hwdb_new (udev);
+	if (hwdb == NULL)
+		goto bail;
+
+	modalias = g_strdup_printf ("OUI:%c%c%c%c%c%c",
+				    g_ascii_toupper (oui[0]),
+				    g_ascii_toupper (oui[1]),
+				    g_ascii_toupper (oui[3]),
+				    g_ascii_toupper (oui[4]),
+				    g_ascii_toupper (oui[6]),
+				    g_ascii_toupper (oui[7]));
+
+	list = udev_hwdb_get_properties_list_entry (hwdb, modalias, 0);
+
+	udev_list_entry_foreach (l, list) {
+		const char *name = udev_list_entry_get_name (l);
+
+		if (g_strcmp0 (name, "ID_OUI_FROM_DATABASE") == 0) {
+			vendor = g_strdup (udev_list_entry_get_value (l));
+			break;
+		}
+	}
+
+bail:
+	g_clear_pointer (&modalias, g_free);
+	g_clear_pointer (&hwdb, udev_hwdb_unref);
+	g_clear_pointer (&udev, udev_unref);
+
+	return vendor;
+}
+
+#define TYPE_IS(x, r) {				\
+	if (g_str_equal(type, x)) return r;	\
+}
+
+static guint string_to_type(const char *type)
+{
+	TYPE_IS ("any", BLUETOOTH_TYPE_ANY);
+	TYPE_IS ("mouse", BLUETOOTH_TYPE_MOUSE);
+	TYPE_IS ("tablet", BLUETOOTH_TYPE_TABLET);
+	TYPE_IS ("keyboard", BLUETOOTH_TYPE_KEYBOARD);
+	TYPE_IS ("headset", BLUETOOTH_TYPE_HEADSET);
+	TYPE_IS ("headphones", BLUETOOTH_TYPE_HEADPHONES);
+	TYPE_IS ("audio", BLUETOOTH_TYPE_OTHER_AUDIO);
+	TYPE_IS ("printer", BLUETOOTH_TYPE_PRINTER);
+	TYPE_IS ("network", BLUETOOTH_TYPE_NETWORK);
+
+	g_warning ("unhandled type '%s'", type);
+	return BLUETOOTH_TYPE_ANY;
+}
+
+typedef struct {
+	char *ret_pin;
+	guint max_digits;
+	guint type;
+	const char *address;
+	const char *name;
+	char *vendor;
+	gboolean confirm;
+} PinParseData;
+
+static void
+pin_db_parse_start_tag (GMarkupParseContext *ctx,
+			const gchar         *element_name,
+			const gchar        **attr_names,
+			const gchar        **attr_values,
+			gpointer             data,
+			GError             **error)
+{
+	PinParseData *pdata = (PinParseData *) data;
+
+	if (pdata->ret_pin != NULL || pdata->max_digits != 0)
+		return;
+	if (g_str_equal (element_name, "device") == FALSE)
+		return;
+
+	while (*attr_names && *attr_values) {
+		if (g_str_equal (*attr_names, "type")) {
+			guint type;
+
+			type = string_to_type (*attr_values);
+			if (type != BLUETOOTH_TYPE_ANY && type != pdata->type)
+				return;
+		} else if (g_str_equal (*attr_names, "oui")) {
+			if (g_str_has_prefix (pdata->address, *attr_values) == FALSE)
+				return;
+		} else if (g_str_equal (*attr_names, "vendor")) {
+			if (*attr_values == NULL || pdata->vendor == NULL)
+				return;
+			if (strstr (pdata->vendor, *attr_values) == NULL)
+				return;
+		} else if (g_str_equal (*attr_names, "name")) {
+			if (*attr_values == NULL || pdata->name == NULL)
+				return;
+			if (strstr (pdata->name, *attr_values) == NULL)
+				return;
+			pdata->confirm = FALSE;
+		} else if (g_str_equal (*attr_names, "pin")) {
+			if (g_str_has_prefix (*attr_values, MAX_DIGITS_PIN_PREFIX) != FALSE) {
+				pdata->max_digits = strtoul (*attr_values + strlen (MAX_DIGITS_PIN_PREFIX), NULL, 0);
+				g_assert (pdata->max_digits > 0 && pdata->max_digits < PIN_NUM_DIGITS);
+			} else {
+				pdata->ret_pin = g_strdup (*attr_values);
+			}
+			return;
+		}
+
+		++attr_names;
+		++attr_values;
+	}
+}
+
+char *
+get_pincode_for_device (guint       type,
+			const char *address,
+			const char *name,
+			guint      *max_digits,
+			gboolean   *confirm)
+{
+	GMarkupParseContext *ctx;
+	GMarkupParser parser = { pin_db_parse_start_tag, NULL, NULL, NULL, NULL };
+	PinParseData data;
+	char *buf;
+	gsize buf_len;
+	GError *err = NULL;
+	char *tmp_vendor;
+
+	g_return_val_if_fail (address != NULL, NULL);
+
+	g_debug ("Getting pincode for device '%s' (type: %s address: %s)",
+		 name ? name : "", bluetooth_type_to_string (type), address);
+
+	/* Load the PIN database and split it in lines */
+	if (!g_file_get_contents(PIN_CODE_DB, &buf, &buf_len, NULL)) {
+		char *filename;
+
+		filename = g_build_filename(PKGDATADIR, PIN_CODE_DB, NULL);
+		if (!g_file_get_contents(filename, &buf, &buf_len, NULL)) {
+			g_warning("Could not load "PIN_CODE_DB);
+			g_free (filename);
+			return NULL;
+		}
+		g_free (filename);
+	}
+
+	data.ret_pin = NULL;
+	data.max_digits = 0;
+	data.type = type;
+	data.address = address;
+	data.name = name;
+	data.confirm = TRUE;
+
+	tmp_vendor = oui_to_vendor (address);
+	data.vendor = g_ascii_strdown (tmp_vendor, -1);
+	g_free (tmp_vendor);
+
+	ctx = g_markup_parse_context_new (&parser, 0, &data, NULL);
+
+	if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err)) {
+		g_warning ("Failed to parse '%s': %s\n", PIN_CODE_DB, err->message);
+		g_error_free (err);
+	}
+
+	g_markup_parse_context_free (ctx);
+	g_free (buf);
+
+	if (max_digits != NULL)
+		*max_digits = data.max_digits;
+	if (confirm != NULL)
+		*confirm = data.confirm;
+
+	g_debug ("Got pin '%s' (max digits: %d, confirm: %d) for device '%s' (type: %s address: %s, vendor: %s)",
+		 data.ret_pin, data.max_digits, data.confirm,
+		 name ? name : "", bluetooth_type_to_string (type), address, data.vendor);
+
+	g_free (data.vendor);
+
+	return data.ret_pin;
+}
+
diff --git a/lib/pin.h b/lib/pin.h
new file mode 100644
index 0000000..db7d323
--- /dev/null
+++ b/lib/pin.h
@@ -0,0 +1,34 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009  Bastien Nocera <hadess@hadess.net>
+ *
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <glib.h>
+
+#define PIN_NUM_DIGITS 6
+
+char *oui_to_vendor (const char *oui);
+char *get_pincode_for_device (guint       type,
+			      const char *address,
+			      const char *name,
+			      guint      *max_digits,
+			      gboolean   *confirm);
+
diff --git a/lib/plugins/Makefile.am b/lib/plugins/Makefile.am
deleted file mode 100644
index e867443..0000000
--- a/lib/plugins/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-plugindir = $(libdir)/mate-bluetooth/plugins/
-
-INCLUDES =                                      \
-        -DDATADIR=\"$(datadir)\"                \
-        -DICONDIR=\"$(icondir)\"                \
-	-DLOCALEDIR="\"$(datadir)/locale\""	\
-        -I$(top_srcdir)/lib			\
-        -I$(top_builddir)			\
-	$(PLUGINS_CFLAGS)			\
-	$(LIBMATEBT_CFLAGS)			\
-	$(GEOCLUE_CFLAGS)			\
-	$(WARN_CFLAGS)
-
-plugin_LTLIBRARIES = libgbtgeoclue.la
-
-libgbtgeoclue_la_SOURCES = geoclue.c
-libgbtgeoclue_la_LDFLAGS = -module -avoid-version
-libgbtgeoclue_la_LIBADD = $(PLUGINS_LIBS) $(GEOCLUE_LIBS)
-
-testplugin_LTLIBRARIES = libgbttest.la
-
-testplugindir = $(libdir)/mate-bluetooth/plugins/
-
-libgbttest_la_SOURCES = test.c
-libgbttest_la_LDFLAGS = -module -avoid-version
-libgbttest_la_LIBADD = $(PLUGINS_LIBS)
-
-# override to _not_ install the test plugins
-install-testpluginLTLIBRARIES:
-
diff --git a/lib/plugins/geoclue.c b/lib/plugins/geoclue.c
deleted file mode 100644
index 11c662d..0000000
--- a/lib/plugins/geoclue.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2009  Bastien Nocera <hadess@hadess.net>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-
-#include <gtk/gtk.h>
-#include <bluetooth-plugin.h>
-#include <gio/gio.h>
-
-#include "bluetooth-client.h"
-
-/* http://cgit.freedesktop.org/geoclue/tree/src/org.freedesktop.Geoclue.gschema.xml */
-#define GPS_SCHEMA "org.freedesktop.Geoclue"
-#define GPS_KEY "gps-device"
-
-static gboolean
-gsettings_schema_exists(const char *schema)
-{
-	const char * const *schemas;
-	gboolean schema_exists = FALSE;
-	gint i;
-
-	schemas = g_settings_list_schemas ();
-	for (i = 0; schemas[i] != NULL; i++) {
-		if (g_strcmp0 (schemas[i], schema) == 0) {
-			schema_exists = TRUE;
-			break;
-		}
-	}
-
-	return schema_exists;
-}
-
-static char *
-get_name_and_type (const char *address, BluetoothType *ret_type)
-{
-	BluetoothClient *client;
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	gboolean cont;
-	char *found_name;
-
-	found_name = NULL;
-	*ret_type = 0;
-	client = bluetooth_client_new (); 
-	model = bluetooth_client_get_device_model (client, NULL);
-	if (model == NULL) {
-		g_object_unref (client);
-		return NULL;
-	}
-
-	cont = gtk_tree_model_get_iter_first(model, &iter);
-	while (cont != FALSE) {
-		char *bdaddr, *name;
-		BluetoothType type;
-
-		gtk_tree_model_get(model, &iter,
-				   BLUETOOTH_COLUMN_ADDRESS, &bdaddr,
-				   BLUETOOTH_COLUMN_ALIAS, &name,
-				   BLUETOOTH_COLUMN_TYPE, &type,
-				   -1);
-		if (g_strcmp0 (bdaddr, address) == 0) {
-			g_free (bdaddr);
-			found_name = name;
-			*ret_type = type;
-			break;
-		}
-		g_free (bdaddr);
-		g_free (name);
-
-		cont = gtk_tree_model_iter_next(model, &iter);
-	}
-
-	g_object_unref (model);
-	g_object_unref (client);
-
-	return found_name;
-}
-
-static gboolean
-has_config_widget (const char *bdaddr, const char **uuids)
-{
-	gboolean has_sp = FALSE;
-	BluetoothType type;
-	char *name;
-	guint i;
-
-	if (uuids == NULL)
-		return FALSE;
-	for (i = 0; uuids[i] != NULL; i++) {
-		if (g_str_equal (uuids[i], "SerialPort")) {
-			has_sp = TRUE;
-			break;
-		}
-	}
-	if (has_sp == FALSE)
-		return FALSE;
-
-	/* Just SP? Probably a GPS */
-	if (g_strv_length ((char **) uuids) == 1)
-		return TRUE;
-
-	/* Type is ANY, probably a GPS device */
-	name = get_name_and_type (bdaddr, &type);
-	if (name != NULL && type == BLUETOOTH_TYPE_ANY) {
-		g_free (name);
-		return TRUE;
-	}
-
-	if (name == NULL)
-		return FALSE;
-	/* GPS in the name? */
-	if (strstr (name, "GPS") != NULL) {
-		g_free (name);
-		return TRUE;
-	}
-
-	g_free (name);
-	return FALSE;
-}
-
-static void
-toggle_button (GtkToggleButton *button, gpointer user_data)
-{
-	gboolean state;
-	GSettings *settings;
-	const char *bdaddr;
-
-	settings = g_object_get_data (G_OBJECT (button), "settings");
-	bdaddr = g_object_get_data (G_OBJECT (button), "bdaddr");
-
-	state = gtk_toggle_button_get_active (button);
-	if (state == FALSE) {
-		const char *old_bdaddr;
-		old_bdaddr = g_object_get_data (G_OBJECT (button), "old-bdaddr");
-		g_settings_set_string (settings, GPS_KEY, old_bdaddr ? old_bdaddr : "");
-	} else {
-		char *old_bdaddr;
-
-		old_bdaddr = g_settings_get_string (settings, GPS_KEY);
-		g_object_set_data_full (G_OBJECT (button), "old-bdaddr",
-					old_bdaddr, g_free);
-		g_settings_set_string (settings, GPS_KEY, bdaddr);
-	}
-}
-
-static GtkWidget *
-get_config_widgets (const char *bdaddr, const char **uuids)
-{
-	GtkWidget *button;
-	GSettings *settings = NULL;
-	char *old_bdaddr;
-
-	if (gsettings_schema_exists (GPS_SCHEMA))
-		settings = g_settings_new (GPS_SCHEMA);
-	if (settings == NULL)
-		return NULL;
-
-	button = gtk_check_button_new_with_label (_("Use this GPS device for Geolocation services"));
-	g_object_set_data_full (G_OBJECT (button), "bdaddr", g_strdup (bdaddr), g_free);
-	g_object_set_data_full (G_OBJECT (button), "settings", settings, g_object_unref);
-
-	/* Is it already setup? */
-	old_bdaddr = g_settings_get_string (settings, GPS_KEY);
-	if (g_strcmp0 (old_bdaddr, bdaddr) == 0) {
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
-		g_object_set_data (G_OBJECT (button), "bdaddr", old_bdaddr);
-	} else {
-		g_free (old_bdaddr);
-	}
-
-	/* And set the signal */
-	g_signal_connect (G_OBJECT (button), "toggled",
-			  G_CALLBACK (toggle_button), NULL);
-
-	return button;
-}
-
-static void
-device_removed (const char *bdaddr)
-{
-	GSettings *settings = NULL;
-	char *str;
-
-	if (gsettings_schema_exists (GPS_SCHEMA))
-		settings = g_settings_new (GPS_SCHEMA);
-	if (settings == NULL)
-		return;
-
-	str = g_settings_get_string (settings, GPS_KEY);
-	if (g_strcmp0 (str, bdaddr) == 0) {
-		g_settings_set_string (settings, GPS_KEY, "");
-		g_message ("Device '%s' got disabled as a Geoclue GPS", bdaddr);
-	}
-
-	g_free (str);
-	g_object_unref (settings);
-}
-
-static GbtPluginInfo plugin_info = {
-	"geoclue",
-	has_config_widget,
-	get_config_widgets,
-	device_removed
-};
-
-GBT_INIT_PLUGIN(plugin_info)
-
diff --git a/lib/plugins/test.c b/lib/plugins/test.c
deleted file mode 100644
index 26618b5..0000000
--- a/lib/plugins/test.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2009  Bastien Nocera <hadess@hadess.net>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-
-#include <gtk/gtk.h>
-#include <bluetooth-plugin.h>
-
-static gboolean
-has_config_widget (const char *bdaddr, const char **uuids)
-{
-	guint i;
-
-	if (uuids == NULL)
-		return FALSE;
-	for (i = 0; uuids[i] != NULL; i++) {
-		if (g_str_equal (uuids[i], "PANU"))
-			return TRUE;
-	}
-	return FALSE;
-}
-
-static GtkWidget *
-get_config_widgets (const char *bdaddr, const char **uuids)
-{
-	/* translators:
-	 * This is in a test plugin, please make sure you add the "(test)" part,
-	 * or leave untranslated */
-	return gtk_check_button_new_with_label (_("Access the Internet using your cell phone (test)"));
-}
-
-static void
-device_removed (const char *bdaddr)
-{
-	g_message ("Device '%s' got removed", bdaddr);
-}
-
-static GbtPluginInfo plugin_info = {
-	"test-plugin",
-	has_config_widget,
-	get_config_widgets,
-	device_removed
-};
-
-GBT_INIT_PLUGIN(plugin_info)
-
diff --git a/lib/test-agent.c b/lib/test-agent.c
index 8d60da6..6878774 100644
--- a/lib/test-agent.c
+++ b/lib/test-agent.c
@@ -31,49 +31,34 @@
 #include <signal.h>
 
 #include "bluetooth-agent.h"
-#include "bluetooth-client-glue.h"
 
-static gboolean agent_pincode(DBusGMethodInvocation *context,
-					DBusGProxy *device, gpointer user_data)
+static void
+agent_confirm (GDBusMethodInvocation *invocation,
+	       GDBusProxy *device,
+	       guint passkey,
+	       gpointer data)
 {
-	GHashTable *hash = NULL;
-	GValue *value;
-	const gchar *address, *name;
+	const char *path;
 
-	device_get_properties(device, &hash, NULL);
+	path = g_dbus_proxy_get_object_path(device);
 
-	if (hash != NULL) {
-		value = g_hash_table_lookup(hash, "Address");
-		address = value ? g_value_get_string(value) : NULL;
+	g_print ("Confirming passkey %6.6d from %s\n", passkey, path);
 
-		value = g_hash_table_lookup(hash, "Name");
-		name = value ? g_value_get_string(value) : NULL;
-	} else {
-		address = NULL;
-		name = NULL;
-	}
-
-	printf("address %s name %s\n", address, name);
-
-	dbus_g_method_return(context, "1234");
-
-	return TRUE;
+	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
 static GMainLoop *mainloop = NULL;
 
-static void sig_term(int sig)
+static void
+sig_term (int sig)
 {
 	g_main_loop_quit(mainloop);
 }
 
-int main(int argc, char *argv[])
+int main (int argc, char **argv)
 {
 	struct sigaction sa;
 	BluetoothAgent *agent;
-	DBusGConnection *conn;
-	DBusGProxy *proxy;
-	GError *error = NULL;
 
 	memset(&sa, 0, sizeof(sa));
 	sa.sa_flags = SA_NOCLDSTOP;
@@ -81,38 +66,20 @@ int main(int argc, char *argv[])
 	sigaction(SIGTERM, &sa, NULL);
 	sigaction(SIGINT,  &sa, NULL);
 
-	g_type_init();
-
 	mainloop = g_main_loop_new(NULL, FALSE);
 
-	conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-	if (error != NULL) {
-		g_printerr("Connecting to system bus failed: %s\n",
-							error->message);
-		g_main_loop_unref(mainloop);
-		g_error_free(error);
-		exit(1);
-	}
-
-	proxy = dbus_g_proxy_new_for_name(conn, "org.bluez", "/hci0",
-							"org.bluez.Adapter");
-
 	agent = bluetooth_agent_new();
 
-	bluetooth_agent_set_pincode_func(agent, agent_pincode, NULL);
+	bluetooth_agent_set_confirm_func(agent, agent_confirm, NULL);
 
-	bluetooth_agent_register(agent, proxy);
+	bluetooth_agent_register(agent);
 
 	g_main_loop_run(mainloop);
 
-	//bluetooth_agent_unregister(agent);
+	bluetooth_agent_unregister(agent);
 
 	g_object_unref(agent);
 
-	g_object_unref(proxy);
-
-	dbus_g_connection_unref(conn);
-
 	g_main_loop_unref(mainloop);
 
 	return 0;
diff --git a/lib/test-class.c b/lib/test-class.c
index 06eea06..73e405b 100644
--- a/lib/test-class.c
+++ b/lib/test-class.c
@@ -30,6 +30,7 @@
 
 #include "bluetooth-client.h"
 #include "bluetooth-client-private.h"
+#include "bluetooth-utils.h"
 
 static const char *
 byte_to_binary (int x)
@@ -57,6 +58,7 @@ int main(int argc, char *argv[])
 
 	class = g_ascii_strtoull (argv[1], NULL, 0);
 
+	g_message ("device class: 0x%X", class);
 	g_message ("major class: 0x%X %s", (class & 0x1f00) >> 8, byte_to_binary ((class & 0x1f00) >> 8));
 
 	g_message ("%d %s", bluetooth_class_to_type (class), bluetooth_type_to_string (bluetooth_class_to_type (class)));
diff --git a/lib/test-client.c b/lib/test-client.c
index 9579699..fcfa23f 100644
--- a/lib/test-client.c
+++ b/lib/test-client.c
@@ -27,11 +27,10 @@
 
 #include <gtk/gtk.h>
 
-#include <dbus/dbus-glib.h>
-
 #include "bluetooth-client.h"
 #include "bluetooth-client-private.h"
 #include "mate-bluetooth-enum-types.h"
+#include "bluetooth-utils.h"
 
 static BluetoothClient *client;
 static GtkTreeSelection *selection;
@@ -46,7 +45,7 @@ static void delete_callback(GtkWidget *window, GdkEvent *event,
 
 static void scan_callback(GtkWidget *button, gpointer user_data)
 {
-	bluetooth_client_start_discovery(client);
+	g_object_set (G_OBJECT (client), "default-adapter-discovering", TRUE, NULL);
 }
 
 static void select_callback(GtkTreeSelection *selection, gpointer user_data)
@@ -59,7 +58,7 @@ static void select_callback(GtkTreeSelection *selection, gpointer user_data)
 		return;
 	}
 
-	bluetooth_client_dump_device (model, &iter, FALSE);
+	bluetooth_client_dump_device (model, &iter);
 }
 
 static void row_inserted(GtkTreeModel *model, GtkTreePath *path,
@@ -73,7 +72,7 @@ static void row_inserted(GtkTreeModel *model, GtkTreePath *path,
 static void proxy_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
 		GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
 {
-	DBusGProxy *proxy;
+	GDBusProxy *proxy;
 	gchar *path;
 
 	gtk_tree_model_get(model, iter, BLUETOOTH_COLUMN_PROXY, &proxy, -1);
@@ -83,7 +82,7 @@ static void proxy_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
 		return;
 	}
 
-	path = g_path_get_basename(dbus_g_proxy_get_path(proxy));
+	path = g_path_get_basename(g_dbus_proxy_get_object_path(proxy));
 
 	g_object_set(cell, "text", path, NULL);
 
@@ -103,39 +102,23 @@ static void type_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
 }
 
 static void
-services_foreach (const char *service, gpointer value, GString *str)
+legacypairing_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
+		      GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
 {
-	GEnumClass *eclass;
-	GEnumValue *ev;
-	BluetoothStatus status = GPOINTER_TO_INT (value);
-
-	eclass = g_type_class_ref (BLUETOOTH_TYPE_STATUS);
-	ev = g_enum_get_value (eclass, status);
-	if (ev == NULL)
-		g_warning ("Unknown status value %d", status);
-
-	g_string_append_printf (str, "%s (%s) ", service, ev ? ev->value_nick : "unknown");
-	g_type_class_unref (eclass);
-}
-
-static void services_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
-		GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
-{
-	GString *str;
-	GHashTable *services;
-
-	gtk_tree_model_get(model, iter, BLUETOOTH_COLUMN_SERVICES, &services, -1);
-	if (services == NULL) {
-		g_object_set(cell, "text", NULL, NULL);
-		return;
+	gint legacypairing;
+
+	gtk_tree_model_get(model, iter, BLUETOOTH_COLUMN_LEGACYPAIRING, &legacypairing, -1);
+
+	switch (legacypairing) {
+	case -1:
+		g_object_set(cell, "text", "UNSET", NULL);
+		break;
+	case 0:
+		g_object_set(cell, "text", "FALSE", NULL);
+		break;
+	default:
+		g_object_set(cell, "text", "TRUE", NULL);
 	}
-
-	str = g_string_new (NULL);
-	g_hash_table_foreach (services, (GHFunc) services_foreach, str);
-	g_object_set(cell, "text", str->str, NULL);
-	g_string_free (str, TRUE);
-
-	g_hash_table_unref (services);
 }
 
 static void uuids_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
@@ -254,10 +237,6 @@ static void create_window(void)
 					"text", BLUETOOTH_COLUMN_POWERED, NULL);
 
 	gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree), -1,
-					"Services", gtk_cell_renderer_text_new(),
-						services_to_text, NULL, NULL);
-
-	gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(tree), -1,
 					"UUIDs", gtk_cell_renderer_text_new(),
 						uuids_to_text, NULL, NULL);
 
@@ -305,6 +284,17 @@ default_adapter_powered_changed (GObject    *gobject,
 	g_message ("Default adapter is %s", powered ? "powered" : "switched off");
 }
 
+static void
+default_adapter_discovering_changed (GObject    *gobject,
+				     GParamSpec *pspec,
+				     gpointer    user_data)
+{
+	gboolean discovering;
+
+	g_object_get (G_OBJECT (gobject), "default-adapter-discovering", &discovering, NULL);
+	g_message ("Default adapter is %s", discovering ? "discovering" : "not discovering");
+}
+
 int main(int argc, char *argv[])
 {
 	GLogLevelFlags fatal_mask;
@@ -320,6 +310,8 @@ int main(int argc, char *argv[])
 			  G_CALLBACK (default_adapter_changed), NULL);
 	g_signal_connect (G_OBJECT (client), "notify::default-adapter-powered",
 			  G_CALLBACK (default_adapter_powered_changed), NULL);
+	g_signal_connect (G_OBJECT (client), "notify::default-adapter-discovering",
+			  G_CALLBACK (default_adapter_discovering_changed), NULL);
 
 	default_adapter_changed (G_OBJECT (client), NULL, NULL);
 	default_adapter_powered_changed (G_OBJECT (client), NULL, NULL);
diff --git a/lib/test-deviceselection.c b/lib/test-deviceselection.c
index 6271bb8..a6a3c61 100644
--- a/lib/test-deviceselection.c
+++ b/lib/test-deviceselection.c
@@ -32,6 +32,7 @@
 #include "bluetooth-chooser-button.h"
 #include "bluetooth-chooser-combo.h"
 #include "bluetooth-client.h"
+#include "bluetooth-utils.h"
 #include "bluetooth-filter-widget.h"
 
 static void dump_selected_device(BluetoothChooser *sel)
diff --git a/lib/test-pin.c b/lib/test-pin.c
new file mode 100644
index 0000000..7403c06
--- /dev/null
+++ b/lib/test-pin.c
@@ -0,0 +1,29 @@
+#include "pin.c"
+#include "bluetooth-enums.h"
+
+int main (int argc, char **argv)
+{
+	guint max_digits;
+	gboolean confirm;
+	char *pin;
+
+	g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+
+#if 0
+	pin = get_pincode_for_device (BLUETOOTH_TYPE_KEYBOARD,
+				      "00:13:6C:00:00:00",
+				      "TomTom Remote",
+				      &max_digits,
+				      &confirm);
+#endif
+	pin = get_pincode_for_device (BLUETOOTH_TYPE_MOUSE,
+				      "0C:77:1A:00:00:00",
+				      "Some Apple mouse",
+				      &max_digits,
+				      &confirm);
+
+	g_message ("pin: %s max digits: %d confirm: %d",
+		   pin, max_digits, confirm);
+
+	return 0;
+}
diff --git a/lib/test-plugins.c b/lib/test-plugins.c
deleted file mode 100644
index 2875d86..0000000
--- a/lib/test-plugins.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#include <gtk/gtk.h>
-#include <dbus/dbus-glib.h>
-#include "bluetooth-plugin-manager.h"
-
-static gchar *bdaddr = NULL;
-static gchar **uuids = NULL;
-static gboolean list_uuid = FALSE;
-
-static gboolean
-delete_event_cb (GtkWidget *widget,
-		 GdkEvent  *event,
-		 gpointer   user_data)
-{
-	gtk_main_quit ();
-	return FALSE;
-}
-
-static GOptionEntry options[] = {
-	{ "device", 0, 0, G_OPTION_ARG_STRING, &bdaddr,
-				"Remote device to use", "ADDRESS" },
-	{ "uuid", 0, 0, G_OPTION_ARG_STRING_ARRAY, &uuids,
-				"UUID(s) to test against", "UUID" },
-	{ "list-uuids", 0, 0, G_OPTION_ARG_NONE, &list_uuid,
-				"List valid UUIDs", NULL },
-	{ NULL },
-};
-
-int main (int argc, char **argv)
-{
-	GtkWidget *window, *vbox;
-	GList *list, *l;
-	DBusGConnection *bus;
-	GError *error = NULL;
-
-	if (gtk_init_with_args (&argc, &argv, NULL,
-				options, NULL, &error) == FALSE) {
-		if (error != NULL) {
-			g_printerr ("%s\n", error->message);
-			g_error_free (error);
-		} else
-			g_printerr ("An unknown error occurred\n");
-
-		return 1;
-	}
-
-	if (list_uuid) {
-		g_print ("Valid UUIDs are:\n");
-		/* UUIDs copied from bluetooth-client.c and sorted (do not translate them) */
-		g_print ("AudioSink\n" \
-			 "AudioSource\n" \
-			 "A/V_RemoteControl\n" \
-			 "A/V_RemoteControlTarget\n" \
-			 "DialupNetworking\n" \
-			 "GenericAudio\n" \
-			 "GenericNetworking\n" \
-			 "GN\n" \
-			 "HandsfreeAudioGateway\n" \
-			 "Handsfree\n" \
-			 "Headset_-_AG\n" \
-			 "HSP\n" \
-			 "HumanInterfaceDeviceService\n" \
-			 "IrMCSync\n" \
-			 "NAP\n" \
-			 "OBEXFileTransfer\n" \
-			 "OBEXObjectPush\n" \
-			 "PANU\n" \
-			 "Phonebook_Access_-_PSE\n" \
-			 "PnPInformation\n" \
-			 "SEMC HLA\n" \
-			 "SEMC Watch Phone\n" \
-			 "SerialPort\n" \
-			 "ServiceDiscoveryServerServiceClassID\n" \
-			 "SIM_Access\n" \
-			 "VideoSource\n");
-
-		return 0;
-	}
-
-	/* Init the dbus-glib types */
-	bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
-	dbus_g_connection_unref (bus);
-
-	bluetooth_plugin_manager_init ();
-
-	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-	g_signal_connect (G_OBJECT (window), "delete-event",
-			  G_CALLBACK (delete_event_cb), NULL);
-	vbox = gtk_vbox_new (FALSE, 6);
-	gtk_container_add (GTK_CONTAINER (window), vbox);
-
-	list = bluetooth_plugin_manager_get_widgets (bdaddr, (const char **) uuids);
-	if (list == NULL) {
-		g_message ("no plugins");
-		return 1;
-	}
-
-	for (l = list; l != NULL; l = l->next) {
-		GtkWidget *widget = l->data;
-		gtk_container_add (GTK_CONTAINER (vbox), widget);
-	}
-
-	gtk_widget_show_all (window);
-
-	gtk_main ();
-
-	gtk_widget_destroy (window);
-
-	bluetooth_plugin_manager_cleanup ();
-
-	return 0;
-}
diff --git a/moblin/Makefile.am b/moblin/Makefile.am
deleted file mode 100644
index 8fab969..0000000
--- a/moblin/Makefile.am
+++ /dev/null
@@ -1,44 +0,0 @@
-SUBDIRS = moblin-copy-n-paste theme moblin-icons
-
-bin_PROGRAMS = bluetooth-panel
-
-bluetooth_panel_SOURCES = main.c moblin-panel.c moblin-panel.h
-
-bluetooth_panel_LDADD = $(top_builddir)/lib/libcommon.la $(top_builddir)/lib/libmate-bluetooth.la \
-			$(top_builddir)/moblin/moblin-copy-n-paste/libmoblin.la \
-			$(top_builddir)/wizard/libwizard.la $(MOBLIN_LIBS)
-
-AM_CFLAGS = $(MOBLIN_CFLAGS) $(WARN_CFLAGS) $(DISABLE_DEPRECATED) -DPKGDATADIR="\"$(pkgdatadir)\""
-
-INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/wizard -I$(top_srcdir)/moblin/moblin-copy-n-paste
-
-ui_DATA = pin.ui
-uidir = $(pkgdatadir)
-
-
-desktop_in_files = bluetooth-panel.desktop.in.in
-desktop_data = $(desktop_in_files:.desktop.in.in=.desktop)
-@INTLTOOL_DESKTOP_RULE@
-
-autostartdir = $(sysconfdir)/xdg/autostart
-autostart_DATA = $(desktop_data)
-
-paneldir = @PANEL_DIR@
-panel_DATA = $(desktop_data)
-
-servicedir = $(datadir)/dbus-1/services
-service_in_files = org.moblin.UX.Shell.Panels.bluetooth.service.in
-service_DATA = org.moblin.UX.Shell.Panels.bluetooth.service
-
-@INTLTOOL_DESKTOP_RULE@
-
-CLEANFILES = $(autostart_DATA)
-
-EXTRA_DIST = $(autostart_in_in_files) $(ui_DATA) $(service_DATA)
-
-MAINTAINERCLEANFILES = Makefile.in
-
-DISTCLEANFILES = $(service_DATA)
-
-%.service: %.service.in
-	$(QUIET_GEN)sed -e "s|\@bindir\@|$(bindir)|" $< > $@
diff --git a/moblin/bluetooth-panel.desktop.in.in b/moblin/bluetooth-panel.desktop.in.in
deleted file mode 100644
index 2b875ee..0000000
--- a/moblin/bluetooth-panel.desktop.in.in
+++ /dev/null
@@ -1,16 +0,0 @@
-[Desktop Entry]
-Version=1.0
-_Name=Moblin Bluetooth Panel
-_Comment=Bluetooth Manager Panel
-Icon=bluetooth
-Exec=bluetooth-panel
-Terminal=false
-Type=Application
-OnlyShowIn=MOBLIN;
-X-MATE-Autostart-enable=true
-X-Moblin-Priority=Low
-X-Moblin-Service=org.moblin.UX.Shell.Panels.bluetooth
-X-Moblin-Panel-Optional=true
-X-Moblin-Panel-Type=applet
-X-Moblin-Panel-Stylesheet=@THEME_DIR@/bluetooth-panel.css
-X-Moblin-Panel-Button-Style=state-idle
diff --git a/moblin/main.c b/moblin/main.c
deleted file mode 100644
index 0531c3b..0000000
--- a/moblin/main.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2009, Intel Corporation.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *  Written by: Joshua Lock <josh@linux.intel.com>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <glib/gi18n.h>
-#include <mx/mx-gtk.h>
-#include <moblin-panel/mpl-panel-common.h>
-#include <moblin-panel/mpl-panel-gtk.h>
-#include <bluetooth-enums.h>
-
-#include "moblin-panel.h"
-
-static void
-bluetooth_status_changed (MoblinPanel *panel, gboolean connecting, gpointer user_data)
-{
-	MplPanelClient *client = MPL_PANEL_CLIENT (user_data);
-	gchar *style = NULL;
-
-	if (connecting) {
-		style = g_strdup ("state-connecting");
-	} else {
-		style = g_strdup ("state-idle");
-	}
-
-	mpl_panel_client_request_button_style (client, style);
-	g_free (style);
-}
-
-static void
-panel_request_focus (MoblinPanel *panel, gpointer user_data)
-{
-	MplPanelClient *client = MPL_PANEL_CLIENT (user_data);
-
-	mpl_panel_client_request_focus (client);
-}
-
-/*
- * When the panel is hidden we should re-set the MoblinPanel to its default state.
- * i.e. stop any discovery and show the defaults devices view
- */
-static void
-_reset_view_cb (MplPanelClient *client, gpointer user_data)
-{
-	MoblinPanel *panel = MOBLIN_PANEL (user_data);
-
-	moblin_panel_reset_view (panel);
-}
-
-int
-main (int argc, char *argv[])
-{
-	MplPanelClient *panel;
-	GtkWidget      *window, *content;
-	GtkRequisition  req;
-	gboolean        standalone = FALSE;
-	GtkSettings    *settings;
-	GError         *error = NULL;
-	GOptionEntry    entries[] = {
-		{ "standalone", 's', 0, G_OPTION_ARG_NONE, &standalone,
-		_("Run in standalone mode"), NULL },
-		{ NULL }
-	};
-
-	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-	textdomain (GETTEXT_PACKAGE);
-
-	g_set_application_name (_("Moblin Bluetooth Panel"));
-	gtk_init_with_args (&argc, &argv, _("- Moblin Bluetooth Panel"),
-				entries, GETTEXT_PACKAGE, &error);
-
-	if (error) {
-		g_printerr ("%s\n", error->message);
-		g_error_free (error);
-		return 1;
-	}
-
-	gtk_window_set_default_icon_name ("bluetooth");
-
-	/* Force to correct theme */
-	settings = gtk_settings_get_default ();
-	gtk_settings_set_string_property (settings, "gtk-theme-name",
-					"Moblin-Netbook", NULL);
-
-	if (standalone) {
-		window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-		g_signal_connect (window, "delete-event", (GCallback) gtk_main_quit,
-				NULL);
-		gtk_widget_set_size_request (window, 1000, -1);
-		content = moblin_panel_new ();
-		gtk_widget_show (content);
-
-		gtk_container_add (GTK_CONTAINER (window), content);
-		gtk_widget_show (window);
-	}  else {
-		panel = mpl_panel_gtk_new (MPL_PANEL_BLUETOOTH, _("bluetooth"),
-					THEME_DIR "/bluetooth-panel.css",
-					"state-idle", TRUE);
-		window  = mpl_panel_gtk_get_window (MPL_PANEL_GTK (panel));
-
-		content = moblin_panel_new ();
-		g_signal_connect (panel, "hide-end", (GCallback) _reset_view_cb, content);
-		g_signal_connect (content, "state-changed",
-				G_CALLBACK (bluetooth_status_changed), panel);
-		g_signal_connect (content, "request-focus",
-				  G_CALLBACK (panel_request_focus), panel);
-		gtk_widget_show (content);
-
-		gtk_container_add (GTK_CONTAINER (window), content);
-		gtk_widget_size_request (window, &req);
-		mpl_panel_client_set_height_request (panel, req.height);
-	}
-
-	gtk_main ();
-
-	return 0;
-}
diff --git a/moblin/moblin-copy-n-paste/Makefile.am b/moblin/moblin-copy-n-paste/Makefile.am
deleted file mode 100644
index 3c9d2f1..0000000
--- a/moblin/moblin-copy-n-paste/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-noinst_LTLIBRARIES = libmoblin.la
-libmoblin_la_CFLAGS = $(MOBLIN_CFLAGS) \
-	              -DPKG_DATADIR=\"$(pkgdatadir)\" -Wall
-libmoblin_la_LIBADD = $(MOBLIN_LIBS)
-libmoblin_la_SOURCES = koto-cell-renderer-pixbuf.c \
-		       koto-cell-renderer-pixbuf.h \
-		       mux-cell-renderer-text.c \
-		       mux-cell-renderer-text.h
diff --git a/moblin/moblin-copy-n-paste/koto-cell-renderer-pixbuf.c b/moblin/moblin-copy-n-paste/koto-cell-renderer-pixbuf.c
deleted file mode 100644
index b4ab170..0000000
--- a/moblin/moblin-copy-n-paste/koto-cell-renderer-pixbuf.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2007 OpenedHand Ltd
- *
- * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <config.h>
-#include "koto-cell-renderer-pixbuf.h"
-
-G_DEFINE_TYPE (KotoCellRendererPixbuf,
-               koto_cell_renderer_pixbuf,
-               GTK_TYPE_CELL_RENDERER_PIXBUF);
-
-enum {
-  ACTIVATED,
-  LAST_SIGNAL,
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/*
- * Utility function to determine if a point is inside a rectangle
- */
-G_GNUC_CONST static gboolean
-contains (GdkRectangle *rect, int x, int y)
-{
-  return (rect->x + rect->width) > x && rect->x <= x &&
-    (rect->y + rect->height) > y && rect->y <= y;
-}
-
-static gboolean
-koto_cell_renderer_pixbuf_activate (GtkCellRenderer *cell,
-                                    GdkEvent *event, GtkWidget *widget,
-                                    const gchar *path,
-                                    GdkRectangle *background_area,
-                                    GdkRectangle *cell_area,
-                                    GtkCellRendererState flags)
-{
-  gdouble x, y;
-
-  if (event && gdk_event_get_coords (event, &x, &y)) {
-    if (contains (cell_area, (int)x, (int)y)) {
-      g_signal_emit (cell, signals[ACTIVATED], 0, path);
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-/*
- * Object methods
- */
-
-static void
-koto_cell_renderer_pixbuf_class_init (KotoCellRendererPixbufClass *class)
-{
-  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
-
-  cell_class->activate = koto_cell_renderer_pixbuf_activate;
-
-  signals[ACTIVATED] =
-    g_signal_new ("activated",
-                  G_OBJECT_CLASS_TYPE (class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (KotoCellRendererPixbufClass, activated),
-                  NULL, NULL,
-                  g_cclosure_marshal_VOID__STRING,
-                  G_TYPE_NONE, 1, G_TYPE_STRING);
-}
-
-static void
-koto_cell_renderer_pixbuf_init (KotoCellRendererPixbuf *cellpixbuf)
-{
-  GTK_CELL_RENDERER (cellpixbuf)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
-}
-
-/*
- * Public methods
- */
-
-GtkCellRenderer *
-koto_cell_renderer_pixbuf_new (void)
-{
-  return g_object_new (KOTO_TYPE_CELL_RENDERER_PIXBUF, NULL);
-}
diff --git a/moblin/moblin-copy-n-paste/koto-cell-renderer-pixbuf.h b/moblin/moblin-copy-n-paste/koto-cell-renderer-pixbuf.h
deleted file mode 100644
index 990f44b..0000000
--- a/moblin/moblin-copy-n-paste/koto-cell-renderer-pixbuf.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2007 OpenedHand Ltd
- *
- * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef __KOTO_CELL_RENDERER_PIXBUF_H__
-#define __KOTO_CELL_RENDERER_PIXBUF_H__
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define KOTO_TYPE_CELL_RENDERER_PIXBUF			(koto_cell_renderer_pixbuf_get_type ())
-#define KOTO_CELL_RENDERER_PIXBUF(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), KOTO_TYPE_CELL_RENDERER_PIXBUF, KotoCellRendererPixbuf))
-#define KOTO_CELL_RENDERER_PIXBUF_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), KOTO_TYPE_CELL_RENDERER_PIXBUF, KotoCellRendererPixbufClass))
-#define KOTO_IS_CELL_RENDERER_PIXBUF(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KOTO_TYPE_CELL_RENDERER_PIXBUF))
-#define KOTO_IS_CELL_RENDERER_PIXBUF_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), KOTO_TYPE_CELL_RENDERER_PIXBUF))
-#define KOTO_CELL_RENDERER_PIXBUF_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), KOTO_TYPE_CELL_RENDERER_PIXBUF, KotoCellRendererPixbufClass))
-
-typedef struct _KotoCellRendererPixbuf KotoCellRendererPixbuf;
-typedef struct _KotoCellRendererPixbufClass KotoCellRendererPixbufClass;
-
-struct _KotoCellRendererPixbuf
-{
-  GtkCellRendererPixbuf parent;
-};
-
-struct _KotoCellRendererPixbufClass
-{
-  GtkCellRendererPixbufClass parent_class;
-
-  void (* activated) (KotoCellRendererPixbuf *cell, const char *path);
-};
-
-GType koto_cell_renderer_pixbuf_get_type (void) G_GNUC_CONST;
-GtkCellRenderer *koto_cell_renderer_pixbuf_new (void);
-
-G_END_DECLS
-
-#endif /* __KOTO_CELL_RENDERER_PIXBUF_H__ */
diff --git a/moblin/moblin-copy-n-paste/mux-cell-renderer-text.c b/moblin/moblin-copy-n-paste/mux-cell-renderer-text.c
deleted file mode 100644
index c6ce31e..0000000
--- a/moblin/moblin-copy-n-paste/mux-cell-renderer-text.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "mux-cell-renderer-text.h"
-
-G_DEFINE_TYPE (MuxCellRendererText,
-	       mux_cell_renderer_text,
-	       GTK_TYPE_CELL_RENDERER_TEXT)
-
-enum {
-  ACTIVATED,
-  LAST_SIGNAL,
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static gboolean
-contains (GdkRectangle *rect, gint x, gint y)
-{
-  return (rect->x + rect->width) > x && rect->x <= x &&
-  	 (rect->y + rect->height) > y && rect->y <= y;
-}
-
-static gboolean
-mux_cell_renderer_text_activate (GtkCellRenderer     *cell,
-				 GdkEvent            *event,
-				 GtkWidget           *widget,
-				 const gchar         *path,
-				 GdkRectangle        *bg_area,
-				 GdkRectangle        *cell_area,
-				 GtkCellRendererState flags)
-{
-  gdouble x, y;
-
-  if (event) {
-    gdk_event_get_coords (event, &x, &y);
-    if (contains (cell_area, (gint) x, (gint) y)) {
-      g_signal_emit (cell, signals[ACTIVATED], 0, path);
-
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-static void
-mux_cell_renderer_text_render (GtkCellRenderer     *cell,
-			       GdkDrawable         *window,
-			       GtkWidget           *widget,
-			       GdkRectangle        *bg_area,
-			       GdkRectangle        *cell_area,
-			       GdkRectangle        *expose_area,
-			       GtkCellRendererState flags)
-{
-  GTK_CELL_RENDERER_CLASS (mux_cell_renderer_text_parent_class)->render (cell,
-                                                                         window,
-                                                                         widget,
-                                                                         bg_area,
-                                                                         cell_area,
-                                                                         expose_area,
-                                                                         GTK_CELL_RENDERER_SELECTED);
-}
-
-
-static void
-mux_cell_renderer_text_class_init (MuxCellRendererTextClass *klass)
-{
-  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
-
-  cell_class->activate = mux_cell_renderer_text_activate;
-  cell_class->render = mux_cell_renderer_text_render;
-
-  signals[ACTIVATED] =
-    g_signal_new ("activated",
-    		  G_OBJECT_CLASS_TYPE (klass),
-    		  G_SIGNAL_RUN_LAST,
-    		  G_STRUCT_OFFSET (MuxCellRendererTextClass, activated),
-    		  NULL,
-    		  NULL,
-    		  g_cclosure_marshal_VOID__STRING,
-    		  G_TYPE_NONE, 1, G_TYPE_STRING);
-}
-
-static void
-mux_cell_renderer_text_init (MuxCellRendererText *self)
-{
-  GTK_CELL_RENDERER (self)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
-}
-
-GtkCellRenderer*
-mux_cell_renderer_text_new (void)
-{
-  return g_object_new (MUX_TYPE_CELL_RENDERER_TEXT, NULL);
-}
diff --git a/moblin/moblin-copy-n-paste/mux-cell-renderer-text.h b/moblin/moblin-copy-n-paste/mux-cell-renderer-text.h
deleted file mode 100644
index 5bb78d1..0000000
--- a/moblin/moblin-copy-n-paste/mux-cell-renderer-text.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _MUX_CELL_RENDERER_TEXT
-#define _MUX_CELL_RENDERER_TEXT
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define MUX_TYPE_CELL_RENDERER_TEXT mux_cell_renderer_text_get_type()
-
-#define MUX_CELL_RENDERER_TEXT(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUX_TYPE_CELL_RENDERER_TEXT, MuxCellRendererText))
-
-#define MUX_CELL_RENDERER_TEXT_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), MUX_TYPE_CELL_RENDERER_TEXT, MuxCellRendererTextClass))
-
-#define MUX_IS_CELL_RENDERER_TEXT(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUX_TYPE_CELL_RENDERER_TEXT))
-
-#define MUX_IS_CELL_RENDERER_TEXT_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), MUX_TYPE_CELL_RENDERER_TEXT))
-
-#define MUX_CELL_RENDERER_TEXT_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), MUX_TYPE_CELL_RENDERER_TEXT, MuxCellRendererTextClass))
-
-typedef struct {
-  GtkCellRendererText parent;
-} MuxCellRendererText;
-
-typedef struct {
-  GtkCellRendererTextClass parent_class;
-  void (*activated) (MuxCellRendererText *cell, const gchar *path);
-} MuxCellRendererTextClass;
-
-GType mux_cell_renderer_text_get_type (void);
-
-GtkCellRenderer* mux_cell_renderer_text_new (void);
-
-G_END_DECLS
-
-#endif /* _MUX_CELL_RENDERER_TEXT */
-
diff --git a/moblin/moblin-icons/Makefile.am b/moblin/moblin-icons/Makefile.am
deleted file mode 100644
index f0d2d39..0000000
--- a/moblin/moblin-icons/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-iconsdir = $(pkgdatadir)/moblin-icons
-
-icons_DATA = \
-	bluetooth-idle-hover.png \
-	bluetooth-idle.png \
-	bluetooth-connecting-hover.png \
-	bluetooth-connecting.png \
-	toolbar-button-hover.png \
-	toolbar-button-active.png
-
-EXTRA_DIST = $(icons_DATA)
diff --git a/moblin/moblin-icons/bluetooth-connecting-hover.png b/moblin/moblin-icons/bluetooth-connecting-hover.png
deleted file mode 100644
index 2646199..0000000
Binary files a/moblin/moblin-icons/bluetooth-connecting-hover.png and /dev/null differ
diff --git a/moblin/moblin-icons/bluetooth-connecting.png b/moblin/moblin-icons/bluetooth-connecting.png
deleted file mode 100644
index efd798d..0000000
Binary files a/moblin/moblin-icons/bluetooth-connecting.png and /dev/null differ
diff --git a/moblin/moblin-icons/bluetooth-idle-hover.png b/moblin/moblin-icons/bluetooth-idle-hover.png
deleted file mode 100644
index 1f4dc5a..0000000
Binary files a/moblin/moblin-icons/bluetooth-idle-hover.png and /dev/null differ
diff --git a/moblin/moblin-icons/bluetooth-idle.png b/moblin/moblin-icons/bluetooth-idle.png
deleted file mode 100644
index 433b435..0000000
Binary files a/moblin/moblin-icons/bluetooth-idle.png and /dev/null differ
diff --git a/moblin/moblin-icons/toolbar-button-active.png b/moblin/moblin-icons/toolbar-button-active.png
deleted file mode 100644
index be2db8c..0000000
Binary files a/moblin/moblin-icons/toolbar-button-active.png and /dev/null differ
diff --git a/moblin/moblin-icons/toolbar-button-hover.png b/moblin/moblin-icons/toolbar-button-hover.png
deleted file mode 100644
index dfdf73b..0000000
Binary files a/moblin/moblin-icons/toolbar-button-hover.png and /dev/null differ
diff --git a/moblin/moblin-panel.c b/moblin/moblin-panel.c
deleted file mode 100644
index bdc7c41..0000000
--- a/moblin/moblin-panel.c
+++ /dev/null
@@ -1,1719 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2009  Bastien Nocera <hadess@hadess.net>
- *  Copyright (C) 2009, Intel Corporation.
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *  Written by: Joshua Lock <josh@linux.intel.com>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <math.h>
-#include <gdk/gdkkeysyms.h>
-#include <mx/mx-gtk.h>
-
-#include "bluetooth-client.h"
-#include "bluetooth-client-private.h"
-#include "bluetooth-chooser.h"
-#include "bluetooth-chooser-private.h"
-#include "bluetooth-killswitch.h"
-#include "bluetooth-plugin-manager.h"
-#include "bluetooth-filter-widget.h"
-#include "bluetooth-agent.h"
-#include "mate-bluetooth-enum-types.h"
-
-#include "pin.h"
-
-#include "mux-cell-renderer-text.h"
-#include "koto-cell-renderer-pixbuf.h"
-
-#include "moblin-panel.h"
-
-G_DEFINE_TYPE (MoblinPanel, moblin_panel, GTK_TYPE_HBOX)
-
-#define MOBLIN_PANEL_GET_PRIVATE(o)                                         \
-  (G_TYPE_INSTANCE_GET_PRIVATE ((o), MOBLIN_TYPE_PANEL, MoblinPanelPrivate))
-
-struct _MoblinPanelPrivate
-{
-	/* Bluetooth objects for interacting with BlueZ */
-	BluetoothKillswitch *killswitch;
-	BluetoothClient *client;
-	BluetoothAgent *agent;
-	GtkTreeModel *chooser_model;
-
-	/* Page widgets that need to be "globally" accessible */
-	GtkWidget *power_switch;
-	GtkWidget *notebook;
-	GtkWidget *label_pin_help;
-	GtkWidget *label_pin;
-	GtkWidget *label_ssp_pin_help;
-	GtkWidget *label_ssp_pin;
-	GtkWidget *summary_frame;
-	GtkWidget *extra_config_vbox;
-	GtkWidget *label_failure;
-	GtkWidget *chooser;
-	GtkWidget *display;
-	GtkWidget *send_button;
-	GtkWidget *add_new_button;
-	/* Widgets for use in lazy-loading the pin options dialog from the GtkBuilder UI file */
-	GtkWidget *matches_button;
-	GtkWidget *does_not_match_button;
-	GtkWidget *spinner;
-
-	/* Widgets for use in lazy-loading the pin options dialog from the GtkBuilder UI file */
-	GtkWidget *pin_dialog;
-	GtkWidget *entry_custom;
-	GtkWidget *radio_auto;
-	GtkWidget *radio_0000;
-	GtkWidget *radio_1111;
-	GtkWidget *radio_1234;
-	GtkWidget *radio_custom;
-
-	/* State tracking variables */
-	gchar *pincode;
-	gchar *user_pincode;
-	gchar *target_pincode;
-	gchar *target_name;
-	gchar *target_address;
-	gboolean target_ssp;
-	gboolean automatic_pincode;
-	gboolean create_started;
-	gboolean complete;
-	BluetoothType target_type;
-	gboolean connecting;
-	gboolean display_called;
-};
-
-#define CONNECT_TIMEOUT 3.0
-#define AGENT_PATH "/org/bluez/agent/moblin"
-
-typedef struct {
-	char *path;
-	GTimer *timer;
-	MoblinPanel *self;
-} ConnectData;
-
-typedef enum {
-	PAGE_DEVICES,
-	PAGE_ADD,
-	PAGE_SETUP,
-	PAGE_SSP_SETUP,
-	PAGE_CONNECTING,
-	PAGE_SUMMARY,
-	PAGE_FAILURE
-} MoblinPages;
-
-enum {
-	STATUS_CONNECTING,
-        REQUEST_FOCUS,
-	LAST_SIGNAL
-};
-
-static guint _signals[LAST_SIGNAL] = {0, };
-
-/* Forward declarations of methods */
-static void set_current_page (MoblinPanel *self, MoblinPages page);
-static void create_callback (BluetoothClient *client, const gchar *path, const GError *error, gpointer user_data);
-static void update_random_pincode (MoblinPanel *self);
-static void create_selected_device (MoblinPanel *self);
-
-static void
-power_switch_toggled_cb (MxGtkLightSwitch *light_switch,
-			 gboolean 	     state,
-                         gpointer            user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE(user_data);
-
-	if (state == TRUE) {
-		bluetooth_killswitch_set_state (priv->killswitch, KILLSWITCH_STATE_UNBLOCKED);
-	} else {
-		bluetooth_killswitch_set_state (priv->killswitch, KILLSWITCH_STATE_SOFT_BLOCKED);
-	}
-}
-
-static void
-enable_send_file (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	BluetoothChooser *chooser = BLUETOOTH_CHOOSER (priv->display);
-	GValue value = {0, };
-	gchar *name = NULL;
-	gboolean enabled = FALSE;
-
-	name = bluetooth_chooser_get_selected_device_name (chooser);
-	if (name != NULL) {
-		guint i;
-		const char **uuids;
-
-		g_free (name);
-		bluetooth_chooser_get_selected_device_info (chooser, "uuids", &value);
-
-		uuids = (const char **) g_value_get_boxed (&value);
-		if (uuids != NULL) {
-			for (i = 0; uuids[i] != NULL; i++)
-				if (g_str_equal (uuids[i], "OBEXObjectPush")) {
-					enabled = TRUE;
-					break;
-				}
-			g_value_unset (&value);
-		}
-	}
-	gtk_widget_set_sensitive (priv->send_button, enabled);
-}
-
-static void
-killswitch_state_changed_cb (BluetoothKillswitch *killswitch,
-                             KillswitchState      state,
-                             gpointer             user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	g_signal_handlers_block_by_func (priv->power_switch, power_switch_toggled_cb, user_data);
-
-	if (state == KILLSWITCH_STATE_SOFT_BLOCKED) {
-		mx_gtk_light_switch_set_active (MX_GTK_LIGHT_SWITCH (priv->power_switch),
-	                                      FALSE);
-		gtk_widget_set_sensitive (priv->power_switch, TRUE);
-		gtk_widget_set_sensitive (priv->add_new_button, FALSE);
-		gtk_widget_set_sensitive (priv->send_button, FALSE);
-	} else if (state == KILLSWITCH_STATE_UNBLOCKED) {
-		mx_gtk_light_switch_set_active (MX_GTK_LIGHT_SWITCH (priv->power_switch), TRUE);
-		gtk_widget_set_sensitive (priv->power_switch, TRUE);
-		gtk_widget_set_sensitive (priv->add_new_button, TRUE);
-		enable_send_file (self);
-	} else if (state == KILLSWITCH_STATE_HARD_BLOCKED || state == KILLSWITCH_STATE_NO_ADAPTER) {
-		gtk_widget_set_sensitive (priv->power_switch, FALSE);
-		gtk_widget_set_sensitive (priv->add_new_button, FALSE);
-		gtk_widget_set_sensitive (priv->send_button, FALSE);
-	} else {
-		g_assert_not_reached ();
-	}
-
-	g_signal_handlers_unblock_by_func (priv->power_switch, power_switch_toggled_cb, user_data);
-}
-
-static void
-selected_device_changed_cb (BluetoothChooser *chooser, const char *address, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	enable_send_file (MOBLIN_PANEL (self));
-}
-
-static void
-set_frame_title (GtkFrame *frame, gchar *title)
-{
-	GtkWidget *frame_title;
-	gchar *label = NULL;
-
-	label = g_strdup_printf ("<span font_desc=\"Liberation Sans Bold 18px\""
-	                           "foreground=\"#3e3e3e\">%s</span>", title);
-	frame_title = gtk_frame_get_label_widget (frame);
-	gtk_label_set_markup (GTK_LABEL (frame_title), label);
-	g_free (label);
-	gtk_widget_show (frame_title);
-}
-
-static void
-send_file_button_clicked_cb (GtkButton *button,
-                             gpointer   user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	BluetoothChooser *chooser = BLUETOOTH_CHOOSER (priv->display);
-	GPtrArray *a;
-	GError *err = NULL;
-	guint i;
-	char *address, *name;
-
-	address = bluetooth_chooser_get_selected_device (chooser);
-	name = bluetooth_chooser_get_selected_device_name (chooser);
-
-	a = g_ptr_array_new ();
-	g_ptr_array_add (a, "bluetooth-sendto");
-	if (address != NULL) {
-		char *s;
-
-		s = g_strdup_printf ("--device=\"%s\"", address);
-		g_ptr_array_add (a, s);
-	}
-	if (address != NULL && name != NULL) {
-		char *s;
-
-		s = g_strdup_printf ("--name=\"%s\"", name);
-		g_ptr_array_add (a, s);
-	}
-	g_ptr_array_add (a, NULL);
-
-	g_free (address);
-	g_free (name);
-
-	if (g_spawn_async(NULL, (char **) a->pdata, NULL,
-			  G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err) == FALSE) {
-		g_printerr("Couldn't execute command: %s\n", err->message);
-		g_error_free (err);
-	}
-
-	for (i = 1; a->pdata[i] != NULL; i++)
-		g_free (a->pdata[i]);
-
-	g_ptr_array_free (a, TRUE);
-}
-
-static gboolean
-entry_custom_event (GtkWidget *entry, GdkEventKey *event)
-{
-	if (event->length == 0)
-		return FALSE;
-
-	if ((event->keyval >= GDK_0 && event->keyval <= GDK_9) ||
-	    (event->keyval >= GDK_KP_0 && event->keyval <= GDK_KP_9))
-		return FALSE;
-
-	return TRUE;
-}
-
-static void
-entry_custom_changed (GtkWidget *entry, gpointer user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	priv->user_pincode = g_strdup (gtk_entry_get_text(GTK_ENTRY(entry)));
-	gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->pin_dialog),
-					   GTK_RESPONSE_ACCEPT,
-					   gtk_entry_get_text_length (GTK_ENTRY (entry)) >= 1);
-}
-
-static void
-toggle_set_sensitive (GtkWidget *button, gpointer user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	gboolean active;
-
-	active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
-	gtk_widget_set_sensitive(priv->entry_custom, active);
-	/* When selecting another PIN, make sure the "Close" button is sensitive */
-	if (!active)
-		gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->pin_dialog),
-						   GTK_RESPONSE_ACCEPT, TRUE);
-}
-
-static void
-set_user_pincode (GtkWidget *button, gpointer user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	GSList *list, *l;
-
-	list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
-	for (l = list; l ; l = l->next) {
-		GtkEntry *entry;
-		GtkWidget *radio;
-		const char *pin;
-
-		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
-			continue;
-
-		/* Is it radio_fixed that changed? */
-		radio = g_object_get_data (G_OBJECT (button), "button");
-		if (radio != NULL) {
-			set_user_pincode (radio, user_data);
-			return;
-		}
-
-		pin = g_object_get_data (G_OBJECT (button), "pin");
-		entry = g_object_get_data (G_OBJECT (button), "entry");
-
-		if (entry != NULL) {
-			g_free (priv->user_pincode);
-			priv->user_pincode = g_strdup (gtk_entry_get_text(entry));
-			gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->pin_dialog),
-							   GTK_RESPONSE_ACCEPT,
-							   gtk_entry_get_text_length (entry) >= 1);
-		} else if (pin != NULL) {
-			g_free (priv->user_pincode);
-			if (*pin == '\0')
-				priv->user_pincode = NULL;
-			else
-				priv->user_pincode = g_strdup (pin);
-		}
-
-		break;
-	}
-}
-
-static void
-pin_options_button_clicked_cb (GtkButton *button,
-                             gpointer   user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	GtkWidget *radio;
-	gchar *oldpin;
-	GtkBuilder *builder;
-	GError *err = NULL;
-
-	if (priv->pin_dialog == NULL) {
-		builder = gtk_builder_new ();
-		if (gtk_builder_add_from_file (builder, "pin.ui", NULL) == 0) {
-			if (gtk_builder_add_from_file (builder, PKGDATADIR "/pin.ui", &err) == 0) {
-				g_warning ("Could not load PIN dialog UI form %s: %s",
-					PKGDATADIR "/pin.ui", err->message);
-				g_error_free (err);
-			}
-		}
-
-		priv->pin_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "pin_dialog"));
-		priv->radio_auto  = GTK_WIDGET (gtk_builder_get_object (builder, "radio_auto"));
-		g_signal_connect (priv->radio_auto, "toggled", G_CALLBACK (set_user_pincode), self);
-		priv->radio_0000 = GTK_WIDGET (gtk_builder_get_object (builder, "radio_0000"));
-		g_signal_connect (priv->radio_0000, "toggled", G_CALLBACK (set_user_pincode), self);
-		priv->radio_1111 = GTK_WIDGET (gtk_builder_get_object (builder, "radio_1111"));
-		g_signal_connect (priv->radio_1111, "toggled", G_CALLBACK (set_user_pincode), self);
-		priv->radio_1234 = GTK_WIDGET (gtk_builder_get_object (builder, "radio_1234"));
-		g_signal_connect (priv->radio_1234, "toggled", G_CALLBACK (set_user_pincode), self);
-		priv->radio_custom = GTK_WIDGET (gtk_builder_get_object (builder, "radio_custom"));
-		g_signal_connect (priv->radio_custom, "toggled", G_CALLBACK (set_user_pincode), self);
-		g_signal_connect (priv->radio_custom, "toggled", G_CALLBACK (toggle_set_sensitive), self);
-		priv->entry_custom = GTK_WIDGET (gtk_builder_get_object (builder, "entry_custom"));
-		g_signal_connect (priv->entry_custom, "key-press-event", G_CALLBACK (entry_custom_event), self);
-		g_signal_connect (priv->entry_custom, "changed", G_CALLBACK (entry_custom_changed), self);
-
-		g_object_set_data (G_OBJECT (priv->radio_auto), "pin", "");
-		g_object_set_data (G_OBJECT (priv->radio_0000), "pin", "0000");
-		g_object_set_data (G_OBJECT (priv->radio_1111), "pin", "1111");
-		g_object_set_data (G_OBJECT (priv->radio_1234), "pin", "1234");
-		g_object_set_data (G_OBJECT (priv->radio_custom), "entry", priv->entry_custom);
-
-		gtk_dialog_add_button (GTK_DIALOG (priv->pin_dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
-	}
-
-	oldpin = priv->user_pincode;
-	priv->user_pincode = NULL;
-
-	gtk_window_present (GTK_WINDOW (priv->pin_dialog));
-
-	if (oldpin == NULL)
-		radio = priv->radio_auto;
-	else if (g_str_equal (oldpin, "0000"))
-		radio = priv->radio_0000;
-	else if (g_str_equal (oldpin, "1111"))
-		radio = priv->radio_1111;
-	else if (g_str_equal (oldpin, "1234"))
-		radio = priv->radio_1234;
-	else
-		radio = priv->radio_custom;
-
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);
-	if (radio == priv->radio_custom)
-		gtk_entry_set_text (GTK_ENTRY (priv->entry_custom), oldpin);
-
-	if (gtk_dialog_run (GTK_DIALOG (priv->pin_dialog)) != GTK_RESPONSE_ACCEPT) {
-		g_free (priv->user_pincode);
-		priv->user_pincode = oldpin;
-	} else {
-		g_free (oldpin);
-	}
-
-	gtk_widget_hide (priv->pin_dialog);
-
-        g_signal_emit (self, _signals[REQUEST_FOCUS], 0);
-}
-
-/*
- * This helper function forces the currently selected row in the chooser to be
- * the same row which contains the activated cell.
- */
-static void
-ensure_selection (BluetoothChooser *chooser, const gchar *path)
-{
-	GtkTreeView *view;
-	GtkTreePath *tree_path;
-	view = GTK_TREE_VIEW (bluetooth_chooser_get_treeview (chooser));
-
-	/* Set selection */
-	tree_path = gtk_tree_path_new_from_string (path);
-	gtk_tree_view_set_cursor (view, tree_path, NULL, FALSE);
-	gtk_tree_path_free (tree_path);
-}
-
-static void
-remove_clicked_cb (GtkCellRenderer *cell, const gchar *path, gpointer user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	BluetoothChooser *chooser = BLUETOOTH_CHOOSER (priv->display);
-	const gchar *address = NULL;
-	GValue value = { 0, };
-
-	ensure_selection (chooser, path);
-
-	/* Get address */
-	g_assert (bluetooth_chooser_get_selected_device_info (chooser, "address", &value));
-	address = g_value_get_string (&value);
-
-	if (bluetooth_chooser_remove_selected_device (chooser) != FALSE && address) {
-		bluetooth_plugin_manager_device_deleted (address);
-	}
-
-	g_value_unset (&value);
-}
-
-static void
-browse_clicked (GtkCellRenderer *renderer, const gchar *path, gpointer user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	BluetoothChooser *chooser = BLUETOOTH_CHOOSER (priv->display);
-	const gchar *address = NULL;
-	GValue value = { 0, };
-	gchar *cmd;
-
-	ensure_selection (chooser, path);
-
-	/* Get address */
-	if (bluetooth_chooser_get_selected_device_info (chooser, "address", &value)) {
-		address = g_value_get_string (&value);
-	}
-
-	if (address == NULL) {
-		cmd = g_strdup_printf ("%s --no-default-window \"obex://[%s]\"",
-				       "caja", address);
-		if (!g_spawn_command_line_async (cmd, NULL))
-			g_printerr("Couldn't execute command: %s\n", cmd);
-		g_free (cmd);
-	}
-
-	g_value_unset (&value);
-}
-
-static void
-connect_callback (BluetoothClient *client, gboolean success, gpointer user_data)
-{
-	ConnectData *data = (ConnectData *)user_data;
-
-	if (success == FALSE && g_timer_elapsed (data->timer, NULL) < CONNECT_TIMEOUT) {
-		if (bluetooth_client_connect_service (client, data->path, connect_callback, data) != FALSE)
-			return;
-	}
-
-	if (success == FALSE)
-		g_message ("Failed to connect to device %s", data->path);
-
-	g_timer_destroy (data->timer);
-	g_free (data->path);
-	g_object_unref (data->self);
-	g_free (data);
-}
-
-static void
-set_failure_message (MoblinPanel *self, gchar *device)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	gchar *str;
-
-	str = g_strdup_printf (_("Pairing with %s failed."), device);
-	gtk_label_set_text (GTK_LABEL (priv->label_failure), str);
-}
-
-static void
-set_ssp_pin_message (MoblinPanel *self, gchar *msg)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	gtk_label_set_text (GTK_LABEL (priv->label_ssp_pin_help), msg);
-}
-
-static void
-set_ssp_pin_label (MoblinPanel *self, gchar *pin)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	gchar *str;
-
-	str = g_strdup_printf ("<span font_desc=\"50\" color=\"black\" bgcolor=\"white\">  %s  </span>", pin);
-
-	gtk_label_set_markup (GTK_LABEL (priv->label_ssp_pin), str);
-
-	g_free (str);
-}
-
-static void
-set_pin_message (MoblinPanel *self, gchar *msg)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	gtk_label_set_text (GTK_LABEL (priv->label_pin_help), msg);
-}
-
-static void
-set_pin_label (MoblinPanel *self, gchar *pin)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	gchar *str;
-
-	str = g_strdup_printf ("<span font_desc=\"50\" color=\"black\" bgcolor=\"white\">  %s  </span>", pin);
-
-	gtk_label_set_markup (GTK_LABEL (priv->label_pin), str);
-
-	g_free (str);
-}
-
-static gboolean
-cancel_callback (DBusGMethodInvocation *context, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	priv->create_started  = FALSE;
-	set_current_page (self, PAGE_FAILURE);
-
-	set_failure_message (self, priv->target_name);
-
-	dbus_g_method_return(context);
-
-	return TRUE;
-}
-
-static void
-connect_device (const gchar *device_path, MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	ConnectData *data;
-
-	data = g_new0 (ConnectData, 1);
-	data->path = g_strdup (device_path);
-	data->timer = g_timer_new ();
-	data->self = g_object_ref (self);
-
-	if (bluetooth_client_connect_service (priv->client, device_path, connect_callback, data) == FALSE) {
-		g_timer_destroy (data->timer);
-		g_free (data->path);
-		g_object_unref (data->self);
-		g_free (data);
-	}
-}
-
-static void
-container_remove_all (GtkContainer *container)
-{
-	GList *list;
-	GList *iter;
-
-	list = gtk_container_get_children (container);
-	for (iter = list; iter; iter = iter->next)
-		gtk_container_remove (container, GTK_WIDGET (iter->data));
-
-	g_list_free (list);
-}
-
-static void
-set_current_page (MoblinPanel *self, MoblinPages page)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	if (page == PAGE_ADD) {
-		g_object_set (BLUETOOTH_CHOOSER (priv->chooser),
-			      "device-category-filter", BLUETOOTH_CATEGORY_NOT_PAIRED_OR_TRUSTED,
-			      NULL);
-
-		bluetooth_chooser_start_discovery (BLUETOOTH_CHOOSER (priv->chooser));
-	} else {
-		bluetooth_chooser_stop_discovery (BLUETOOTH_CHOOSER (priv->chooser));
-	}
-
-	if (page == PAGE_CONNECTING)
-		gtk_spinner_start (GTK_SPINNER (priv->spinner));
-	else
-		gtk_spinner_stop (GTK_SPINNER (priv->spinner));
-
-	if ((page == PAGE_SETUP || page == PAGE_SSP_SETUP || page == PAGE_CONNECTING) && (priv->create_started == FALSE)) {
-		create_selected_device (self);
-	}
-
-	if (page == PAGE_SETUP) {
-		priv->complete = FALSE;
-
-		if (priv->automatic_pincode == FALSE && priv->target_ssp == FALSE) {
-			gchar *text;
-
-			if (priv->target_type == BLUETOOTH_TYPE_KEYBOARD) {
-				text = g_strdup_printf (_("Please enter the following PIN on '%s' and press “Enter” on the keyboard:"), priv->target_name);
-			} else {
-				text = g_strdup_printf (_("Please enter the following PIN on '%s':"), priv->target_name);
-			}
-
-			set_pin_message (self, text);
-			set_pin_label (self, priv->pincode);
-		} else {
-			g_assert_not_reached ();
-		}
-	}
-
-	if (page == PAGE_SSP_SETUP && priv->display_called == FALSE) {
-		priv->complete = FALSE;
-		gtk_widget_show (priv->matches_button);
-		gtk_widget_show (priv->does_not_match_button);
-	} else {
-		gtk_widget_hide (priv->matches_button);
-		gtk_widget_hide (priv->does_not_match_button);
-	}
-
-	if (page == PAGE_SUMMARY) {
-		GValue value = { 0, };
-		const char **uuids;
-		GList *widgets;
-		char *title;
-		gboolean have_additional_widgets = FALSE;
-
-		title = g_strdup_printf (_("Successfully set up new device '%s'"), priv->target_name);
-		set_frame_title (GTK_FRAME (priv->summary_frame), title);
-		g_free (title);
-
-		if (bluetooth_chooser_get_selected_device_info (BLUETOOTH_CHOOSER (priv->chooser), "uuids", &value))
-			uuids = g_value_get_boxed (&value);
-		else
-			uuids = NULL;
-
-		widgets = bluetooth_plugin_manager_get_widgets (priv->target_address, uuids);
-		if (widgets) {
-			GList *iter;
-
-			for (iter = widgets; iter; iter = iter->next)
-				gtk_box_pack_start (GTK_BOX (priv->extra_config_vbox),
-						    GTK_WIDGET (iter->data),
-						    FALSE,
-						    TRUE,
-						    0);
-
-			g_list_free (widgets);
-			gtk_widget_show_all (priv->extra_config_vbox);
-			have_additional_widgets = TRUE;
-		}
-
-		g_value_unset (&value);
-
-		if (!have_additional_widgets)
-			/* Show the devices page if we don't have any extra information to present. */
-			page = PAGE_DEVICES;
-	}
-
-	if (page == PAGE_DEVICES) {
-		/* Clean up old state */
-		update_random_pincode (self);
-		priv->target_ssp = FALSE;
-		priv->target_type = BLUETOOTH_TYPE_ANY;
-		priv->display_called = FALSE;
-		g_free (priv->target_address);
-		priv->target_address = NULL;
-		g_free (priv->target_name);
-		priv->target_name = NULL;
-		container_remove_all (GTK_CONTAINER (priv->extra_config_vbox));
-		g_object_set (priv->chooser, "device-type-filter", BLUETOOTH_TYPE_ANY, NULL);
-	}
-
-	gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), page);
-}
-
-static void
-create_callback (BluetoothClient *client, const gchar *path, const GError *error, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	gchar *device_name;
-
-	priv->create_started = FALSE;
-
-	if (path == NULL) {
-		device_name = bluetooth_chooser_get_selected_device_name (BLUETOOTH_CHOOSER (priv->chooser));
-		set_failure_message (self, device_name);
-		g_free (device_name);
-		set_current_page (self, PAGE_FAILURE);
-		return;
-	}
-
-	bluetooth_client_set_trusted (client, path, TRUE);
-
-	connect_device (path, self);
-
-	set_current_page (self, PAGE_SUMMARY);
-}
-
-static void
-create_selected_device (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	const gchar *path = AGENT_PATH;
-	gchar *pin_ret;
-
-	/* Set the filter on the selector, so we can use it to get more
-	 * info later, in page_summary */
-	g_object_set (priv->chooser,
-		      "device-category-filter", BLUETOOTH_CATEGORY_ALL,
-		      NULL);
-
-	pin_ret = get_pincode_for_device (priv->target_type, priv->target_address,
-					priv->target_name, NULL);
-	if (pin_ret != NULL && g_str_equal (pin_ret, "NULL"))
-		path = NULL;
-	g_free (pin_ret);
-
-	g_object_ref (priv->agent);
-	bluetooth_client_create_device (priv->client, priv->target_address, path,
-					create_callback, self);
-	priv->create_started = TRUE;
-}
-
-static void
-pair_clicked (GtkCellRenderer *renderer, const gchar *path, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	GValue value = { 0, };
-	gchar *name;
-	gchar *address = NULL;
-	guint legacy_pairing;
-	BluetoothType type;
-	BluetoothChooser *chooser = BLUETOOTH_CHOOSER (priv->chooser);
-
-	ensure_selection (BLUETOOTH_CHOOSER (priv->chooser), path);
-
-	name = bluetooth_chooser_get_selected_device_name (chooser);
-	type = bluetooth_chooser_get_selected_device_type (chooser);
-	if (bluetooth_chooser_get_selected_device_info (chooser, "address", &value) != FALSE) {
-		address = g_value_dup_string (&value);
-		g_value_unset (&value);
-	}
-	if (bluetooth_chooser_get_selected_device_info (chooser, "legacypairing", &value) != FALSE) {
-		legacy_pairing = g_value_get_int (&value);
-		g_value_unset (&value);
-			if (legacy_pairing == -1)
-				legacy_pairing = TRUE;
-	} else {
-		legacy_pairing = TRUE;
-	}
-
-	g_free (priv->target_address);
-	priv->target_address = address;
-
-	g_free (priv->target_name);
-	priv->target_name = name;
-
-	priv->target_type = type;
-	priv->target_ssp = !legacy_pairing;
-	priv->automatic_pincode = FALSE;
-
-	g_free (priv->pincode);
-	priv->pincode = NULL;
-
-	if (priv->user_pincode != NULL && *priv->user_pincode != '\0') {
-		priv->pincode = g_strdup (priv->user_pincode);
-		priv->automatic_pincode = TRUE;
-	} else if (address != NULL) {
-		guint max_digits;
-
-		priv->pincode = get_pincode_for_device (priv->target_type, priv->target_address,
-							priv->target_name, &max_digits);
-		if (priv->pincode == NULL) {
-			/* Truncate the default pincode if the device doesn't like long
-			 * PIN codes */
-			if (max_digits != PIN_NUM_DIGITS && max_digits > 0)
-				priv->pincode = g_strndup(priv->target_pincode, max_digits);
-			else
-				priv->pincode = g_strdup(priv->target_pincode);
-		} else if (priv->target_ssp == FALSE) {
-			priv->automatic_pincode = TRUE;
-		}
-	}
-
-	if (priv->target_ssp != FALSE || priv->automatic_pincode != FALSE) {
-		set_current_page (self, PAGE_CONNECTING);
-	} else {
-		set_current_page (self, PAGE_SETUP);
-	}
-}
-
-static void
-connect_clicked (GtkCellRenderer *renderer, const gchar *path, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	GValue value = { 0, };
-	DBusGProxy *device;
-	const gchar *device_path = NULL;
-
-	ensure_selection (BLUETOOTH_CHOOSER (priv->display), path);
-
-	bluetooth_chooser_get_selected_device_info (BLUETOOTH_CHOOSER (priv->display), "proxy", &value);
-	device = g_value_get_object (&value);
-	device_path = dbus_g_proxy_get_path (device);
-	g_value_unset (&value);
-
-	connect_device (device_path, self);
-}
-
-static void
-remove_to_icon (GtkTreeViewColumn *column, GtkCellRenderer *cell,
-		GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
-{
-	gboolean paired, trusted;
-	gtk_tree_model_get (model, iter, BLUETOOTH_COLUMN_PAIRED, &paired,
-			BLUETOOTH_COLUMN_TRUSTED, &trusted, -1);
-	if (paired || trusted) {
-		g_object_set (cell, "icon-name", GTK_STOCK_CLEAR, NULL);
-	} else {
-		g_object_set (cell, "icon-name", NULL, NULL);
-	}
-}
-
-static void
-pair_to_text (GtkTreeViewColumn *column, GtkCellRenderer *cell,
-		GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
-{
-	gboolean paired, trusted;
-	gtk_tree_model_get (model, iter, BLUETOOTH_COLUMN_PAIRED, &paired,
-			BLUETOOTH_COLUMN_TRUSTED, &trusted, -1);
-
-	if (!paired && !trusted) {
-		g_object_set (cell, "markup", _("<u>Pair</u>"), NULL);
-	}
-}
-
-static void
-connect_to_text (GtkTreeViewColumn *column, GtkCellRenderer *cell,
-		GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
-{
-	gboolean paired, trusted, connected;
-	gtk_tree_model_get (model, iter, BLUETOOTH_COLUMN_PAIRED, &paired,
-			BLUETOOTH_COLUMN_CONNECTED, &connected,
-			BLUETOOTH_COLUMN_TRUSTED, &trusted, -1);
-
-	if ((paired || trusted) && connected == FALSE) {
-		g_object_set (cell, "markup", _("<u>Connect</u>"), NULL);
-	} else {
-		g_object_set (cell, "markup", "", NULL);
-	}
-}
-
-static void
-browse_to_text (GtkTreeViewColumn *column, GtkCellRenderer *cell,
-		GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
-{
-	gboolean found = FALSE;
-	guint i;
-	char **uuids = NULL;
-
-	gtk_tree_model_get (model, iter, BLUETOOTH_COLUMN_UUIDS, &uuids, -1);
-
-	if (uuids != NULL) {
-		for (i = 0; uuids[i] != NULL; i++)
-			if (g_str_equal (uuids[i], "OBEXFileTransfer")) {
-				g_object_set (cell, "markup", _("<u>Browse</u>"), NULL);
-				found = TRUE;
-				break;
-			}
-		g_strfreev (uuids);
-	}
-
-	if (found == FALSE)
-		g_object_set (cell, "markup", "", NULL);
-}
-
-static void
-set_scanning_view (GtkButton *button, MoblinPanel *self)
-{
-	set_current_page (self, PAGE_ADD);
-}
-
-static void
-set_device_view (GtkButton *button, MoblinPanel *self)
-{
-	set_current_page (self, PAGE_DEVICES);
-}
-
-static void
-determine_connecting (const gchar *key, gpointer value, gpointer user_data)
-{
-	BluetoothStatus status = GPOINTER_TO_INT (value);
-	BluetoothStatus *other_status = user_data;
-
-	if (status == BLUETOOTH_STATUS_CONNECTING)
-		(*other_status) = status;
-}
-
-static void
-have_connecting_device (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	GHashTable *states = NULL;
-	GtkTreeIter iter;
-	BluetoothStatus status = BLUETOOTH_STATUS_INVALID;
-	gboolean connecting = FALSE;
-
-	if (gtk_tree_model_get_iter_first (priv->chooser_model, &iter) == TRUE)
-	{
-		gtk_tree_model_get(priv->chooser_model, &iter, BLUETOOTH_COLUMN_SERVICES, &states, -1);
-
-		if (states) {
-			g_hash_table_foreach (states, (GHFunc) determine_connecting, &status);
-
-			g_hash_table_unref (states);
-		}
-
-		if (status == BLUETOOTH_STATUS_CONNECTING)
-			connecting = TRUE;
-
-		if (connecting != priv->connecting) {
-			priv->connecting = connecting;
-			g_signal_emit (self, _signals[STATUS_CONNECTING], 0,
-				priv->connecting);
-		}
-	}
-}
-
-static void
-model_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
-{
-	have_connecting_device (MOBLIN_PANEL (user_data));
-}
-
-static void
-row_deleted_cb (GtkTreeModel *model, GtkTreePath *path, gpointer user_data)
-{
-	have_connecting_device (MOBLIN_PANEL (user_data));
-}
-
-static void
-does_not_match_cb (GtkButton *button, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	DBusGMethodInvocation *context;
-	GError *error = NULL;
-
-	set_current_page (self, PAGE_FAILURE);
-
-	set_failure_message (self, priv->target_name);
-
-	context = g_object_get_data (G_OBJECT (button), "context");
-	g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT, "Agent callback cancelled");
-	dbus_g_method_return (context, error);
-
-	g_object_set_data (G_OBJECT (priv->does_not_match_button), "context", NULL);
-	g_object_set_data (G_OBJECT (priv->matches_button), "context", NULL);
-}
-
-static void
-matches_cb (GtkButton *button, gpointer user_data)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (user_data);
-	DBusGMethodInvocation *context;
-
-	context = g_object_get_data (G_OBJECT (button), "context");
-	gtk_widget_set_sensitive (priv->does_not_match_button, FALSE);
-	gtk_widget_set_sensitive (priv->matches_button, FALSE);
-	dbus_g_method_return (context, "");
-
-	g_object_set_data (G_OBJECT (priv->does_not_match_button), "context", NULL);
-	g_object_set_data (G_OBJECT (priv->matches_button), "context", NULL);
-}
-
-static gboolean
-confirm_callback (DBusGMethodInvocation *context, DBusGProxy *device, guint pin, gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	gchar *text, *label;
-
-	priv->target_ssp = TRUE;
-	set_current_page (self, PAGE_SSP_SETUP);
-
-	text = g_strdup_printf ("%d", pin);
-	label = g_strdup_printf (_("Please confirm that the PIN displayed on '%s' matches this one."),
-				priv->target_name);
-	set_ssp_pin_message (self, label);
-	set_ssp_pin_label (self, text);
-
-	gtk_widget_set_sensitive (priv->does_not_match_button, TRUE);
-	gtk_widget_set_sensitive (priv->matches_button, TRUE);
-
-	g_object_set_data (G_OBJECT (priv->does_not_match_button), "context", context);
-	g_object_set_data (G_OBJECT (priv->matches_button), "context", context);
-
-	return TRUE;
-}
-
-static gboolean
-display_callback (DBusGMethodInvocation *context, DBusGProxy *device, guint pin, guint entered,
-		gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	gchar *text, *code, *done;
-
-	priv->display_called = TRUE;
-	priv->target_ssp = TRUE;
-
-	set_current_page (self, PAGE_SSP_SETUP);
-
-	code = g_strdup_printf ("%d", pin);
-
-	if (entered > 0) {
-		GtkEntry *entry;
-		gunichar invisible;
-		GString *str;
-		guint i;
-
-		entry = GTK_ENTRY (gtk_entry_new ());
-		invisible = gtk_entry_get_invisible_char (entry);
-		g_object_unref (entry);
-
-		str = g_string_new (NULL);
-		for (i = 0; i < entered; i++)
-			g_string_append_unichar (str, invisible);
-		if (entered < strlen (code))
-			g_string_append (str, code + entered);
-
-		done = g_string_free (str, FALSE);
-	} else {
-		done = g_strdup ("");
-	}
-
-	text = g_strdup_printf("%s%s", done, code + entered);
-	set_ssp_pin_message (self, _("Please enter the following PIN:"));
-	set_ssp_pin_label (self, text);
-
-	dbus_g_method_return (context);
-
-	return TRUE;
-}
-
-static GtkWidget *
-create_failure_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page;
-	GtkWidget *page_title;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *back_button;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = mx_gtk_frame_new ();
-	page_title = gtk_label_new ("");
-	gtk_frame_set_label_widget (GTK_FRAME (page), page_title);
-	set_frame_title (GTK_FRAME (page), _("Device setup failed"));
-	gtk_widget_show (page);
-
-	vbox = gtk_vbox_new (FALSE, 6);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (page), vbox);
-	priv->label_failure = gtk_label_new ("");
-	gtk_misc_set_alignment (GTK_MISC (priv->label_failure), 0.0, 0.5);
-	gtk_widget_show (priv->label_failure);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->label_failure, FALSE, FALSE, 6);
-
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 6);
-	back_button = gtk_button_new_with_label (_("Back to devices"));
-	gtk_widget_show (back_button);
-	gtk_box_pack_start (GTK_BOX (hbox), back_button, FALSE, FALSE, 6);
-	g_signal_connect (back_button, "clicked", G_CALLBACK (set_device_view), self);
-
-	return page;
-}
-
-static GtkWidget *
-create_summary_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *w;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = mx_gtk_frame_new ();
-	w = gtk_label_new (NULL);
-	gtk_frame_set_label_widget (GTK_FRAME (page), w);
-	gtk_widget_show (page);
-	priv->summary_frame = page;
-
-	vbox = gtk_vbox_new (FALSE, 12);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (page), vbox);
-	w = gtk_label_new (_("Select the additional services you want to use with your device:"));
-	gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
-	gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 6);
-	gtk_widget_show (w);
-
-	priv->extra_config_vbox = gtk_vbox_new (FALSE, 6);
-	gtk_widget_show (priv->extra_config_vbox);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->extra_config_vbox, TRUE, TRUE, 6);
-
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 6);
-	w = gtk_button_new_with_label (_("Done"));
-	gtk_widget_show (w);
-	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 6);
-	g_signal_connect (w, "clicked", G_CALLBACK (set_device_view), self);
-
-	return page;
-}
-
-static GtkWidget *
-create_setup_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page, *page_title;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *back_button;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = mx_gtk_frame_new ();
-	page_title = gtk_label_new ("");
-	gtk_frame_set_label_widget (GTK_FRAME (page), page_title);
-	set_frame_title (GTK_FRAME (page), _("Device setup"));
-	gtk_widget_show (page);
-
-	vbox = gtk_vbox_new (FALSE, 6);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (page), vbox);
-	priv->label_pin_help = gtk_label_new ("");
-	gtk_widget_show (priv->label_pin_help);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->label_pin_help, FALSE, FALSE, 6);
-	priv->label_pin = gtk_label_new ("");
-	gtk_widget_show (priv->label_pin);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->label_pin, FALSE, FALSE, 6);
-
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 6);
-	back_button = gtk_button_new_with_label (_("Back to devices"));
-	gtk_widget_show (back_button);
-	gtk_box_pack_start (GTK_BOX (hbox), back_button, FALSE, FALSE, 6);
-	g_signal_connect (back_button, "clicked", G_CALLBACK (set_device_view), self);
-
-	return page;
-}
-
-static GtkWidget *
-create_ssp_setup_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page, *page_title;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *back_button;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = mx_gtk_frame_new ();
-	page_title = gtk_label_new ("");
-	gtk_frame_set_label_widget (GTK_FRAME (page), page_title);
-	set_frame_title (GTK_FRAME (page), _("Device setup"));
-	gtk_widget_show (page);
-
-	vbox = gtk_vbox_new (FALSE, 6);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (page), vbox);
-	priv->label_ssp_pin_help = gtk_label_new ("");
-	gtk_widget_show (priv->label_ssp_pin_help);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->label_ssp_pin_help, FALSE, FALSE, 6);
-	priv->label_ssp_pin = gtk_label_new ("");
-	gtk_widget_show (priv->label_ssp_pin);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->label_ssp_pin, FALSE, FALSE, 6);
-
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 6);
-	priv->matches_button = gtk_button_new_with_label (_("Matches"));
-	gtk_widget_show (priv->matches_button);
-	g_signal_connect (priv->matches_button, "clicked", G_CALLBACK (matches_cb), self);
-	gtk_box_pack_start (GTK_BOX (hbox), priv->matches_button, FALSE, FALSE, 6);
-	priv->does_not_match_button = gtk_button_new_with_label (_("Does not match"));
-	gtk_widget_show (priv->does_not_match_button);
-	g_signal_connect (priv->does_not_match_button, "clicked", G_CALLBACK (does_not_match_cb), self);
-	gtk_box_pack_start (GTK_BOX (hbox), priv->does_not_match_button, FALSE, FALSE, 6);
-
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 6);
-	back_button = gtk_button_new_with_label (_("Back to devices"));
-	gtk_widget_show (back_button);
-	gtk_box_pack_start (GTK_BOX (hbox), back_button, FALSE, FALSE, 6);
-	g_signal_connect (back_button, "clicked", G_CALLBACK (set_device_view), self);
-
-	return page;
-}
-
-static GtkWidget *
-create_add_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *filter;
-	GtkWidget *frame_title;
-	GtkWidget *frame;
-	GtkWidget *back_button;
-	GtkWidget *pin_button;
-	GtkWidget *tree_view;
-	GtkTreeViewColumn *type_column;
-	GtkCellRenderer *cell;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = gtk_hbox_new (FALSE, 0);
-	gtk_widget_show (page);
-
-	/* Add child widgetry */
-	vbox = gtk_vbox_new (FALSE, 4);
-	gtk_widget_show (vbox);
-	gtk_box_pack_start (GTK_BOX (page), vbox, TRUE, TRUE, 4);
-
-	frame = mx_gtk_frame_new ();
-	frame_title = gtk_label_new ("");
-	gtk_frame_set_label_widget (GTK_FRAME (frame), frame_title);
-	set_frame_title (GTK_FRAME (frame), _("Devices"));
-
-	/* Device list */
-	priv->chooser = g_object_new (BLUETOOTH_TYPE_CHOOSER,
-				"has-internal-device-filter", FALSE,
-				"show-device-category", FALSE,
-				"show-searching", TRUE,
-				"device-category-filter", BLUETOOTH_CATEGORY_NOT_PAIRED_OR_TRUSTED,
-				NULL);
-	tree_view = bluetooth_chooser_get_treeview (BLUETOOTH_CHOOSER (priv->chooser));
-	g_object_set (tree_view, "enable-grid-lines", TRUE, "headers-visible", FALSE, NULL);
-	type_column = bluetooth_chooser_get_type_column (BLUETOOTH_CHOOSER (priv->chooser));
-	/* Add the pair button */
-	cell = mux_cell_renderer_text_new ();
-	gtk_tree_view_column_pack_start (type_column, cell, FALSE);
-
-	gtk_tree_view_column_set_cell_data_func (type_column, cell,
-						 pair_to_text, self, NULL);
-	g_signal_connect (cell, "activated", G_CALLBACK (pair_clicked), self);
-
-	gtk_widget_show (priv->chooser);
-	gtk_container_add (GTK_CONTAINER (frame), priv->chooser);
-	gtk_widget_show (frame);
-	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 4);
-
-	/* Back button */
-	back_button = gtk_button_new_with_label (_("Back to devices"));
-	gtk_widget_show (back_button);
-	g_signal_connect (back_button, "clicked",
-			G_CALLBACK (set_device_view), self);
-	gtk_box_pack_start (GTK_BOX (vbox), back_button, FALSE, FALSE, 4);
-
-	/* Right column */
-	frame = mx_gtk_frame_new ();
-	gtk_widget_show (frame);
-	vbox = gtk_vbox_new (FALSE, 4);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (frame), vbox);
-	gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 4);
-
-	hbox = gtk_hbox_new (FALSE, 4);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
-
-	/* Filter combo */
-	filter = bluetooth_filter_widget_new ();
-	gtk_widget_show (filter);
-	bluetooth_filter_widget_set_title (BLUETOOTH_FILTER_WIDGET (filter), _("Only show:"));
-	bluetooth_filter_widget_bind_filter (BLUETOOTH_FILTER_WIDGET (filter),
-					     BLUETOOTH_CHOOSER (priv->chooser));
-	gtk_box_pack_start (GTK_BOX (vbox), filter, FALSE, FALSE, 4);
-
-	/* Button for PIN options file */
-	pin_button = gtk_button_new_with_label (_("PIN options"));
-	gtk_widget_show (pin_button);
-	g_signal_connect (pin_button, "clicked",
-                    G_CALLBACK (pin_options_button_clicked_cb), self);
-	gtk_box_pack_start (GTK_BOX (vbox), pin_button, FALSE, FALSE, 4);
-
-	return page;
-}
-
-static GtkWidget *
-create_devices_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page;
-	GtkWidget *frame_title;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *frame;
-	GtkWidget *power_label;
-	GtkTreeViewColumn *type_column;
-	GtkCellRenderer *cell;
-	KillswitchState switch_state;
-	GtkWidget *tree_view;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = gtk_hbox_new (FALSE, 0);
-	gtk_widget_show (page);
-	/* Add child widgetry */
-	vbox = gtk_vbox_new (FALSE, 4);
-	gtk_widget_show (vbox);
-	gtk_box_pack_start (GTK_BOX (page), vbox, TRUE, TRUE, 4);
-
-	frame = mx_gtk_frame_new ();
-	frame_title = gtk_label_new ("");
-	gtk_frame_set_label_widget (GTK_FRAME (frame), frame_title);
-	set_frame_title (GTK_FRAME (frame), _("Devices"));
-
-	/* Device list */
-	priv->display = g_object_new (BLUETOOTH_TYPE_CHOOSER,
-			        "has-internal-device-filter", FALSE,
-				"show-device-category", FALSE,
-				"show-searching", FALSE,
-				"device-category-filter", BLUETOOTH_CATEGORY_PAIRED_OR_TRUSTED,
-				NULL);
-	type_column = bluetooth_chooser_get_type_column (BLUETOOTH_CHOOSER (priv->display));
-	if (!priv->chooser_model) {
-		priv->chooser_model = bluetooth_chooser_get_model (BLUETOOTH_CHOOSER (priv->display));
-		g_signal_connect (priv->chooser_model, "row-changed", G_CALLBACK (model_changed_cb), self);
-		g_signal_connect (priv->chooser_model, "row-deleted", G_CALLBACK (row_deleted_cb), self);
-		g_signal_connect (priv->chooser_model, "row-inserted", G_CALLBACK (model_changed_cb), self);
-	}
-
-	tree_view = bluetooth_chooser_get_treeview (BLUETOOTH_CHOOSER (priv->display));
-	g_object_set (tree_view, "enable-grid-lines", TRUE, "headers-visible", FALSE, NULL);
-
-	/* Add the browse button */
-	cell = mux_cell_renderer_text_new ();
-	gtk_tree_view_column_pack_start (type_column, cell, FALSE);
-
-	gtk_tree_view_column_set_cell_data_func (type_column, cell,
-						 browse_to_text, self, NULL);
-	g_signal_connect (cell, "activated", G_CALLBACK (browse_clicked), self);
-
-	/* Add the connect button */
-	cell = mux_cell_renderer_text_new ();
-	gtk_tree_view_column_pack_start (type_column, cell, FALSE);
-
-	gtk_tree_view_column_set_cell_data_func (type_column, cell,
-						 connect_to_text, self, NULL);
-	g_signal_connect (cell, "activated", G_CALLBACK (connect_clicked), self);
-	/* Add the remove button */
-	cell = koto_cell_renderer_pixbuf_new ();
-	gtk_tree_view_column_pack_end (type_column, cell, FALSE);
-	gtk_tree_view_column_set_cell_data_func (type_column, cell,
-						remove_to_icon, self, NULL);
-	g_signal_connect (cell, "activated", G_CALLBACK (remove_clicked_cb), self);
-
-	gtk_widget_show (priv->display);
-	gtk_container_add (GTK_CONTAINER (frame), priv->display);
-	gtk_widget_show (frame);
-	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 4);
-
-	/* Add new button */
-	priv->add_new_button = gtk_button_new_with_label (_("Add a new device"));
-	gtk_widget_show (priv->add_new_button);
-	g_signal_connect (priv->add_new_button, "clicked",
-			G_CALLBACK (set_scanning_view), self);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->add_new_button, FALSE, FALSE, 4);
-
-	/* Right column */
-	frame = mx_gtk_frame_new ();
-	gtk_widget_show (frame);
-	vbox = gtk_vbox_new (FALSE, 4);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (frame), vbox);
-	gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 4);
-
-	hbox = gtk_hbox_new (FALSE, 4);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 4);
-
-	/* Power switch */
-	/* Translators: This string appears next to a toggle switch which controls
-	 * enabling/disabling Bluetooth radio's on the device. Akin to the power
-	 * switches in the Network UI of Moblin */
-	power_label = gtk_label_new (_("Bluetooth"));
-	gtk_widget_show (power_label);
-	gtk_box_pack_start (GTK_BOX (hbox), power_label, FALSE, FALSE, 4);
-
-	priv->power_switch = mx_gtk_light_switch_new ();
-	if (priv->killswitch != NULL) {
-		if (bluetooth_killswitch_has_killswitches (priv->killswitch) == FALSE) {
-			gtk_widget_set_sensitive (priv->power_switch, FALSE);
-			gtk_widget_set_sensitive (priv->add_new_button, FALSE);
-		} else {
-			switch_state = bluetooth_killswitch_get_state (priv->killswitch);
-
-			switch (switch_state) {
-				case KILLSWITCH_STATE_UNBLOCKED:
-					mx_gtk_light_switch_set_active
-						(MX_GTK_LIGHT_SWITCH (priv->power_switch),
-						 TRUE);
-					gtk_widget_set_sensitive (priv->add_new_button, TRUE);
-					gtk_widget_set_sensitive (priv->power_switch, TRUE);
-				break;
-				case KILLSWITCH_STATE_SOFT_BLOCKED:
-					mx_gtk_light_switch_set_active
-						(MX_GTK_LIGHT_SWITCH (priv->power_switch),
-							FALSE);
-				break;
-				case KILLSWITCH_STATE_HARD_BLOCKED:
-				case KILLSWITCH_STATE_NO_ADAPTER:
-				default:
-					gtk_widget_set_sensitive (priv->power_switch, FALSE);
-					gtk_widget_set_sensitive (priv->add_new_button, FALSE);
-				break;
-			}
-		}
-	} else {
-		gtk_widget_set_sensitive (priv->power_switch, FALSE);
-		gtk_widget_set_sensitive (priv->add_new_button, FALSE);
-	}
-	g_signal_connect  (priv->killswitch, "state-changed",
-			G_CALLBACK (killswitch_state_changed_cb), self);
-	g_signal_connect (priv->power_switch, "switch-flipped",
-			G_CALLBACK (power_switch_toggled_cb), self);
-	gtk_widget_show (priv->power_switch);
-	gtk_box_pack_start (GTK_BOX (hbox), priv->power_switch, FALSE, FALSE, 4);
-
-	/* Button for Send file */
-	priv->send_button = gtk_button_new_with_label (_("Send file from your computer"));
-	gtk_widget_show (priv->send_button);
-	g_signal_connect (priv->send_button, "clicked",
-                    G_CALLBACK (send_file_button_clicked_cb), self);
-	g_signal_connect (priv->display, "selected-device-changed",
-			G_CALLBACK (selected_device_changed_cb), self);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->send_button, FALSE, FALSE, 4);
-
-	enable_send_file (self);
-
-	return page;
-}
-
-static GtkWidget *
-create_connecting_page (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *page, *page_title;
-	GtkWidget *vbox, *hbox;
-	GtkWidget *back_button;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	page = mx_gtk_frame_new ();
-	page_title = gtk_label_new ("");
-	gtk_frame_set_label_widget (GTK_FRAME (page), page_title);
-	//set_frame_title (GTK_FRAME (page), _("Connecting"));
-	gtk_widget_show (page);
-
-	vbox = gtk_vbox_new (FALSE, 6);
-	gtk_widget_show (vbox);
-	gtk_container_add (GTK_CONTAINER (page), vbox);
-	priv->spinner = gtk_spinner_new ();
-	gtk_widget_set_size_request (priv->spinner, 150, 150);
-	gtk_widget_show (priv->spinner);
-	gtk_box_pack_start (GTK_BOX (vbox), priv->spinner, FALSE, FALSE, 6);
-
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_widget_show (hbox);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 6);
-	back_button = gtk_button_new_with_label (_("Back to devices"));
-	gtk_widget_show (back_button);
-	gtk_box_pack_start (GTK_BOX (hbox), back_button, FALSE, FALSE, 6);
-	g_signal_connect (back_button, "clicked", G_CALLBACK (set_device_view), self);
-
-	return page;
-}
-
-static gboolean
-pincode_callback (DBusGMethodInvocation *context,
-		DBusGProxy *device,
-		gpointer user_data)
-{
-	MoblinPanel *self = MOBLIN_PANEL (user_data);
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	priv->target_ssp = FALSE;
-
-	/* Only show the pincode page if the pincode isn't automatic */
-	if (priv->automatic_pincode == FALSE)
-		set_current_page (self, PAGE_SETUP);
-
-	dbus_g_method_return (context, priv->pincode);
-
-	return TRUE;
-}
-
-static void
-update_random_pincode (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (self);
-
-	priv->target_pincode = g_strdup_printf ("%d", g_random_int_range (pow (10, PIN_NUM_DIGITS - 1),
-						pow (10, PIN_NUM_DIGITS) - 1));
-	priv->automatic_pincode = FALSE;
-}
-
-static void
-moblin_panel_init (MoblinPanel *self)
-{
-	MoblinPanelPrivate *priv;
-	GtkWidget *devices_page, *add_page, *setup_page, *ssp_setup_page, *failure_page, *connecting_page;
-	GtkWidget *page;
-
-	priv = MOBLIN_PANEL_GET_PRIVATE (self);
-	priv->pin_dialog = NULL;
-	priv->target_address = NULL;
-	priv->target_name = NULL;
-	priv->target_pincode = NULL;
-	priv->target_type = BLUETOOTH_TYPE_ANY;
-	priv->target_ssp = FALSE;
-	priv->create_started = FALSE;
-	priv->display_called = FALSE;
-	priv->user_pincode = NULL;
-	priv->automatic_pincode = FALSE;
-	priv->pincode = NULL;
-	priv->connecting = FALSE;
-
-	update_random_pincode (self);
-
-	priv->client = bluetooth_client_new ();
-	priv->agent = bluetooth_agent_new ();
-
-	bluetooth_agent_set_pincode_func (priv->agent, pincode_callback, self);
-	bluetooth_agent_set_display_func (priv->agent, display_callback, self);
-	bluetooth_agent_set_cancel_func (priv->agent, cancel_callback, self);
-	bluetooth_agent_set_confirm_func (priv->agent, confirm_callback, self);
-
-	bluetooth_agent_setup (priv->agent, AGENT_PATH);
-
-	priv->killswitch = bluetooth_killswitch_new ();
-	bluetooth_plugin_manager_init ();
-
-	gtk_box_set_homogeneous (GTK_BOX (self), FALSE);
-	gtk_box_set_spacing (GTK_BOX (self), 0);
-
-	priv->notebook = gtk_notebook_new ();
-	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
-	gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
-
-	devices_page = create_devices_page (self);
-	gtk_widget_show (devices_page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), devices_page, NULL);
-
-	add_page = create_add_page (self);
-	gtk_widget_show (add_page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), add_page, NULL);
-
-	setup_page = create_setup_page (self);
-	gtk_widget_show (setup_page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), setup_page, NULL);
-
-	ssp_setup_page = create_ssp_setup_page (self);
-	gtk_widget_show (ssp_setup_page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), ssp_setup_page, NULL);
-
-	connecting_page = create_connecting_page (self);
-	gtk_widget_show (connecting_page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), connecting_page, NULL);
-
-	page = create_summary_page (self);
-	gtk_widget_show (page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), page, NULL);
-
-	failure_page = create_failure_page (self);
-	gtk_widget_show (failure_page);
-	gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), failure_page, NULL);
-
-	set_current_page (self, PAGE_DEVICES);
-	gtk_widget_show (priv->notebook);
-	gtk_box_pack_start (GTK_BOX (self), priv->notebook, TRUE, TRUE, 0);
-}
-
-static void
-moblin_panel_dispose (GObject *object)
-{
-	MoblinPanelPrivate *priv = MOBLIN_PANEL_GET_PRIVATE (object);
-
-	bluetooth_plugin_manager_cleanup ();
-
-	if (priv->killswitch != NULL) {
-		g_object_unref (priv->killswitch);
-		priv->killswitch = NULL;
-	}
-
-	if (priv->agent != NULL) {
-		g_object_unref (priv->agent);
-		priv->agent = NULL;
-	}
-
-	if (priv->client != NULL) {
-		g_object_unref (priv->client);
-		priv->client = NULL;
-	}
-
-	G_OBJECT_CLASS (moblin_panel_parent_class)->dispose (object);
-}
-
-static void
-moblin_panel_class_init (MoblinPanelClass *klass)
-{
-	GObjectClass *obj_class = G_OBJECT_CLASS (klass);
-	g_type_class_add_private (klass, sizeof (MoblinPanelPrivate));
-	obj_class->dispose = moblin_panel_dispose;
-
-	_signals[STATUS_CONNECTING] = g_signal_new ("status-connecting", MOBLIN_TYPE_PANEL,
-						G_SIGNAL_RUN_FIRST,
-						G_STRUCT_OFFSET (MoblinPanelClass, status_connecting),
-						NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
-						G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
-	_signals[REQUEST_FOCUS] = g_signal_new ("request-focus", MOBLIN_TYPE_PANEL,
-						G_SIGNAL_RUN_FIRST,
-                                                0,
-						NULL, NULL, g_cclosure_marshal_VOID__VOID,
-						G_TYPE_NONE, 0);
-}
-
-/**
- * moblin_panel_new:
- *
- * Return value: A #MoblinPanel widget
- **/
-GtkWidget *
-moblin_panel_new (void)
-{
-	return g_object_new (MOBLIN_TYPE_PANEL, NULL);
-}
-
-/**
- *
- * moblin_panel_reset_view:
- *
- * @self: A #MoblinPanel widget
- **/
-void
-moblin_panel_reset_view (MoblinPanel *self)
-{
-	set_current_page (self, PAGE_DEVICES);
-}
diff --git a/moblin/moblin-panel.h b/moblin/moblin-panel.h
deleted file mode 100644
index d273e79..0000000
--- a/moblin/moblin-panel.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library 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
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef _MOBLIN_PANEL_H
-#define _MOBLIN_PANEL_H
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define MOBLIN_TYPE_PANEL moblin_panel_get_type()
-
-#define MOBLIN_PANEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-  MOBLIN_TYPE_PANEL, MoblinPanel))
-
-#define MOBLIN_PANEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), \
-  MOBLIN_TYPE_PANEL, MoblinPanelClass))
-
-#define MOBLIN_IS_PANEL(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-  MOBLIN_TYPE_PANEL))
-
-#define MOBLIN_IS_PANEL_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
-  MOBLIN_TYPE_PANEL))
-
-#define MOBLIN_PANEL_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-  MOBLIN_TYPE_PANEL, MoblinPanelClass))
-
-typedef struct _MoblinPanel MoblinPanel;
-typedef struct _MoblinPanelClass MoblinPanelClass;
-typedef struct _MoblinPanelPrivate MoblinPanelPrivate;
-
-struct _MoblinPanel
-{
-  GtkHBox parent;
-};
-
-struct _MoblinPanelClass
-{
-  GtkHBoxClass parent_class;
-  MoblinPanelPrivate *priv;
-
-  void (*status_connecting) (MoblinPanel *self, gboolean connecting);
-};
-
-GType moblin_panel_get_type (void);
-
-GtkWidget *moblin_panel_new (void);
-
-void moblin_panel_reset_view (MoblinPanel *self);
-
-G_END_DECLS
-
-#endif /* _MOBLIN_PANEL_H */
diff --git a/moblin/pin.ui b/moblin/pin.ui
deleted file mode 100644
index 8b7e1d6..0000000
--- a/moblin/pin.ui
+++ /dev/null
@@ -1,176 +0,0 @@
-<?xml version="1.0"?>
-<interface>
-  <requires lib="gtk+" version="2.16"/>
-  <object class="GtkDialog" id="pin_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">PIN Options</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="type_hint">normal</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child>
-          <object class="GtkVBox" id="vbox1">
-            <property name="visible">True</property>
-            <property name="border_width">12</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">6</property>
-            <child>
-              <object class="GtkRadioButton" id="radio_auto">
-                <property name="label" translatable="yes">_Automatic PIN selection</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_underline">True</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-                <signal name="toggled" handler="set_user_pincode"/>
-              </object>
-              <packing>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label3">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes" comments="Translators: this is a PIN with a set value, such as 1111, or 0000">Fixed PIN</property>
-                <attributes>
-                  <attribute name="weight" value="bold"/>
-                </attributes>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRadioButton" id="radio_0000">
-                <property name="label" translatable="yes">'0000' (most headsets, mice and GPS devices)</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-                <property name="group">radio_auto</property>
-                <signal name="toggled" handler="set_user_pincode"/>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRadioButton" id="radio_1111">
-                <property name="label" translatable="yes">'1111'</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-                <property name="group">radio_auto</property>
-                <signal name="toggled" handler="set_user_pincode"/>
-              </object>
-              <packing>
-                <property name="position">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRadioButton" id="radio_1234">
-                <property name="label" translatable="yes">'1234'</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-                <property name="group">radio_auto</property>
-                <signal name="toggled" handler="set_user_pincode"/>
-              </object>
-              <packing>
-                <property name="position">4</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="hbox1">
-                <property name="visible">True</property>
-                <property name="spacing">12</property>
-                <child>
-                  <object class="GtkRadioButton" id="radio_custom">
-                    <property name="label" translatable="yes">Custom PIN:</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
-                    <property name="active">True</property>
-                    <property name="draw_indicator">True</property>
-                    <property name="group">radio_auto</property>
-                    <signal name="toggled" handler="set_user_pincode"/>
-                    <signal name="toggled" handler="toggle_set_sensitive"/>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="entry_custom">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">True</property>
-                    <property name="max_length">20</property>
-                    <property name="width_chars">20</property>
-                    <signal name="key-press-event" handler="entry_custom_event"/>
-                    <signal name="changed" handler="entry_custom_changed"/>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">5</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="padding">6</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <object class="GtkButton" id="button1">
-                <property name="label">gtk-close</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-3">button1</action-widget>
-    </action-widgets>
-  </object>
-</interface>
diff --git a/moblin/theme/Makefile.am b/moblin/theme/Makefile.am
deleted file mode 100644
index 7c92d04..0000000
--- a/moblin/theme/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-themedir = $(THEME_DIR)
-theme_DATA = bluetooth-panel.css
-
-%.css: %.css.in $(top_builddir)/config.log
-	$(QUIET_GEN)sed -e "s|\@pkgdatadir\@|$(pkgdatadir)|" $< > $@
-
-EXTRA_DIST = bluetooth-panel.css.in
-DISTCLEANFILES = bluetooth-panel.css
diff --git a/moblin/theme/bluetooth-panel.css.in b/moblin/theme/bluetooth-panel.css.in
deleted file mode 100644
index 58f8f05..0000000
--- a/moblin/theme/bluetooth-panel.css.in
+++ /dev/null
@@ -1,28 +0,0 @@
-MnbToolbarButton {
-  background-color: #fff0;
-  border-image: none;
-}
-
-MnbToolbarButton:checked {
-  border-image: url("@pkgdatadir@/moblin-icons/toolbar-button-active.png") 0 stretch;
-}
-
-MnbToolbarButton:hover, MnbToolbarButton:active {
-  border-image: url("@pkgdatadir@/moblin-icons/toolbar-button-hover.png") 0 stretch;
-}
-
-MnbToolbarButton#state-idle {
-  background-image: url("@pkgdatadir@/moblin-icons/bluetooth-idle.png");
-}
-
-MnbToolbarButton#state-idle:hover, MnbToolbarButton#state-idle:active, MnbToolbarButton#state-idle:checked  {
-  background-image: url("@pkgdatadir@/moblin-icons/bluetooth-idle-hover.png");
-}
-
-MnbToolbarButton#state-connecting {
-  background-image: url("@pkgdatadir@/moblin-icons/bluetooth-connecting.png");
-}
-
-MnbToolbarButton#state-connecting:hover, MnbToolbarButton#state-connecting:active, MnbToolbarButton#state-connecting:checked  {
-  background-image: url("@pkgdatadir@/moblin-icons/bluetooth-connecting-hover.png");
-}
diff --git a/properties/Makefile.am b/properties/Makefile.am
index da7e8e0..42e9184 100644
--- a/properties/Makefile.am
+++ b/properties/Makefile.am
@@ -3,7 +3,7 @@ bin_PROGRAMS = mate-bluetooth-properties
 
 mate_bluetooth_properties_SOURCES = main.c general.h general.c adapter.h adapter.c
 
-mate_bluetooth_properties_LDADD = $(top_builddir)/lib/libmate-bluetooth.la $(top_builddir)/lib/libcommon.la $(PROPS_LIBS)
+mate_bluetooth_properties_LDADD = $(top_builddir)/lib/libmate-bluetooth.la $(PROPS_LIBS)
 
 AM_CFLAGS = $(PROPS_CFLAGS) $(WARN_CFLAGS) $(DISABLE_DEPRECATED) -DPKGDATADIR="\"$(pkgdatadir)\""
 
diff --git a/properties/adapter.c b/properties/adapter.c
index 12008b0..032c7e5 100644
--- a/properties/adapter.c
+++ b/properties/adapter.c
@@ -29,8 +29,6 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
-#include <dbus/dbus-glib.h>
-
 #include <bluetooth-client.h>
 #include <bluetooth-client-private.h>
 #include <bluetooth-killswitch.h>
@@ -52,7 +50,7 @@ static GtkNotebook *notebook;
 
 typedef struct adapter_data adapter_data;
 struct adapter_data {
-	DBusGProxy *proxy;
+	GDBusProxy *proxy;
 	GtkWidget *notebook;
 	GtkWidget *child;
 	GtkWidget *button_discoverable;
@@ -88,8 +86,9 @@ static void discoverable_changed_cb(GtkWidget *button, gpointer user_data)
 {
 	/* Note that this would be broken if we showed more than
 	 * one adapter, but we don't care */
+	gboolean value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
 	gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), FALSE);
-	bluetooth_client_set_discoverable (client, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
+	g_object_set (G_OBJECT (client), "default-adapter-discoverable", value, NULL);
 }
 
 static void name_callback(GtkWidget *editable, gpointer user_data)
@@ -103,23 +102,14 @@ static gboolean focus_callback(GtkWidget *editable,
 				GdkEventFocus *event, gpointer user_data)
 {
 	adapter_data *adapter = user_data;
-	GValue value = { 0 };
 	const gchar *text;
 
 	if (!adapter->name_changed)
 		return FALSE;
 
-	g_value_init(&value, G_TYPE_STRING);
-
 	text = gtk_entry_get_text(GTK_ENTRY(editable));
 
-	g_value_set_string(&value, text);
-
-	dbus_g_proxy_call(adapter->proxy, "SetProperty", NULL,
-			G_TYPE_STRING, "Name",
-			G_TYPE_VALUE, &value, G_TYPE_INVALID, G_TYPE_INVALID);
-
-	g_value_unset(&value);
+	g_object_set(adapter->proxy, "Alias", text, NULL);
 
 	adapter->name_changed = 0;
 
@@ -175,7 +165,7 @@ static void disconnect_callback(GtkWidget *button, gpointer user_data)
 {
 	adapter_data *adapter = user_data;
 	GValue value = { 0, };
-	DBusGProxy *device;
+	GDBusProxy *device;
 
 	if (bluetooth_chooser_get_selected_device_info (BLUETOOTH_CHOOSER (adapter->chooser),
 							"proxy", &value) == FALSE) {
@@ -187,8 +177,7 @@ static void disconnect_callback(GtkWidget *button, gpointer user_data)
 	if (device == NULL)
 		return;
 
-	dbus_g_proxy_call(device, "Disconnect", NULL,
-					G_TYPE_INVALID, G_TYPE_INVALID);
+	g_dbus_proxy_call_sync (device, "Disconnect", NULL, G_DBUS_CALL_FLAGS_NONE, 1000, NULL, NULL);
 
 	g_object_unref(device);
 
@@ -218,10 +207,8 @@ set_current_page (GtkNotebook *notebook)
 
 static void create_adapter(adapter_data *adapter)
 {
-	GHashTable *hash = NULL;
-	GValue *value;
-	DBusGProxy *default_proxy;
-	const gchar *name;
+	GVariant *value;
+	gchar *name;
 	gboolean powered, discoverable;
 	guint timeout;
 
@@ -236,41 +223,27 @@ static void create_adapter(adapter_data *adapter)
 	GtkWidget *buttonbox;
 	int page_num;
 
-	dbus_g_proxy_call(adapter->proxy, "GetProperties", NULL, G_TYPE_INVALID,
-				dbus_g_type_get_map("GHashTable",
-						G_TYPE_STRING, G_TYPE_VALUE),
-				&hash, G_TYPE_INVALID);
+	value = g_dbus_proxy_get_cached_property(adapter->proxy, "Alias");
+	name = value ? g_variant_dup_string(value, NULL) : NULL;
+	g_variant_unref(value);
 
-	if (hash != NULL) {
-		value = g_hash_table_lookup(hash, "Name");
-		name = value ? g_value_get_string(value) : NULL;
+	value = g_dbus_proxy_get_cached_property(adapter->proxy, "Powered");
+	powered = value ? g_variant_get_boolean(value) : FALSE;
+	g_variant_unref(value);
 
-		value = g_hash_table_lookup(hash, "Powered");
-		powered = value ? g_value_get_boolean(value) : FALSE;
+	value = g_dbus_proxy_get_cached_property(adapter->proxy, "Discoverable");
+	discoverable = value ? g_variant_get_boolean(value) : FALSE;
+	g_variant_unref(value);
 
-		value = g_hash_table_lookup(hash, "Discoverable");
-		discoverable = value ? g_value_get_boolean(value) : FALSE;
-
-		value = g_hash_table_lookup(hash, "DiscoverableTimeout");
-		timeout = value ? g_value_get_uint(value) : 0;
-	} else {
-		name = NULL;
-		powered = FALSE;
-		discoverable = FALSE;
-		timeout = 0;
-	}
+	value = g_dbus_proxy_get_cached_property(adapter->proxy, "DiscoverableTimeout");
+	timeout = value ? g_variant_get_uint32(value) : 0;
+	g_variant_unref(value);
 
+	adapter->is_default = TRUE;
 	adapter->powered = powered;
 	adapter->discoverable = discoverable;
 	adapter->timeout_value = timeout;
 
-	default_proxy = bluetooth_client_get_default_adapter (client);
-	if (default_proxy != NULL) {
-		adapter->is_default = g_str_equal (dbus_g_proxy_get_path (default_proxy),
-						   dbus_g_proxy_get_path (adapter->proxy));
-		g_object_unref (default_proxy);
-	}
-
 	mainbox = gtk_vbox_new(FALSE, 6);
 	gtk_container_set_border_width(GTK_CONTAINER(mainbox), 12);
 
@@ -319,8 +292,10 @@ static void create_adapter(adapter_data *adapter)
 	gtk_widget_set_size_request(entry, 240, -1);
 	gtk_container_add (GTK_CONTAINER (alignment), entry);
 
-	if (name != NULL)
+	if (name != NULL) {
 		gtk_entry_set_text(GTK_ENTRY(entry), name);
+		g_free(name);
+	}
 
 	adapter->entry = entry;
 	adapter->name_vbox = vbox;
@@ -441,7 +416,7 @@ static void update_visibility(adapter_data *adapter)
 	unblock_signals(adapter);
 }
 
-static void property_changed(DBusGProxy *proxy, const char *property,
+static void property_changed(GDBusProxy *proxy, const char *property,
 					GValue *value, gpointer user_data)
 {
 	adapter_data *adapter = user_data;
@@ -474,7 +449,7 @@ static void property_changed(DBusGProxy *proxy, const char *property,
 static adapter_data *adapter_alloc(GtkTreeModel *model,
 		GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
 {
-	DBusGProxy *proxy;
+	GDBusProxy *proxy;
 	adapter_data *adapter;
 
 	gtk_tree_model_get(model, iter,
@@ -496,8 +471,7 @@ static gboolean adapter_create(gpointer user_data)
 {
 	adapter_data *adapter = user_data;
 
-	dbus_g_proxy_connect_signal(adapter->proxy, "PropertyChanged",
-				G_CALLBACK(property_changed), adapter, NULL);
+// TODO Subscribe to signals?
 
 	create_adapter(adapter);
 
@@ -576,7 +550,7 @@ adapter_changed (GtkTreeModel *model,
 		 GtkTreeIter  *iter,
 		 GtkNotebook  *notebook)
 {
-	DBusGProxy *proxy;
+	GDBusProxy *proxy;
 	int i, count;
 	gboolean is_default, powered;
 	char *name;
@@ -607,7 +581,7 @@ adapter_changed (GtkTreeModel *model,
 		if (proxy == NULL || adapter->proxy == NULL)
 			continue;
 
-		if (g_str_equal (dbus_g_proxy_get_path (proxy), dbus_g_proxy_get_path (adapter->proxy)) != FALSE) {
+		if (g_str_equal (g_dbus_proxy_get_object_path (proxy), g_dbus_proxy_get_object_path (adapter->proxy)) != FALSE) {
 			if (is_default != FALSE && powered != FALSE)
 				gtk_notebook_set_current_page (notebook, i);
 			/* We usually get an adapter_added before the device
diff --git a/properties/main.c b/properties/main.c
index 3830043..c399d19 100644
--- a/properties/main.c
+++ b/properties/main.c
@@ -200,9 +200,9 @@ dump_devices (void)
 		g_print ("Is bluetoothd running, and a Bluetooth adapter enabled?\n");
 		return;
 	}
-	bluetooth_client_dump_device (model, &iter, TRUE);
+	bluetooth_client_dump_device (model, &iter);
 	while (gtk_tree_model_iter_next (model, &iter))
-		bluetooth_client_dump_device (model, &iter, TRUE);
+		bluetooth_client_dump_device (model, &iter);
 }
 
 static gboolean option_dump = FALSE;
diff --git a/sendto/Makefile.am b/sendto/Makefile.am
index e87f44c..4328f16 100644
--- a/sendto/Makefile.am
+++ b/sendto/Makefile.am
@@ -1,7 +1,6 @@
 AM_CFLAGS =                                     \
         -DDATADIR=\"$(datadir)\"                \
         -DICONDIR=\"$(icondir)\"                \
-	-DLOCALEDIR="\"$(datadir)/locale\""	\
 	-I$(top_srcdir)/lib                     \
 	-I$(top_builddir)/lib                   \
 	$(SENDTO_CFLAGS)                        \
@@ -13,9 +12,9 @@ AM_CFLAGS =                                     \
 
 bin_PROGRAMS = mate-bluetooth-sendto
 
-mate_bluetooth_sendto_SOURCES = main.c
+mate_bluetooth_sendto_SOURCES = main.c obex-agent.c
 
-mate_bluetooth_sendto_LDADD = $(top_builddir)/lib/libcommon.la $(top_builddir)/lib/libmate-bluetooth.la $(SENDTO_LIBS)
+mate_bluetooth_sendto_LDADD = $(top_builddir)/lib/libmate-bluetooth.la $(SENDTO_LIBS)
 
 man_MANS = mate-bluetooth-sendto.1
 
diff --git a/sendto/main.c b/sendto/main.c
index 5552184..20a52cf 100644
--- a/sendto/main.c
+++ b/sendto/main.c
@@ -3,6 +3,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2013 Intel Corporation.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -32,21 +33,22 @@
 #include <gio/gio.h>
 #include <gtk/gtk.h>
 
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include <obex-agent.h>
 #include <bluetooth-client.h>
 #include <bluetooth-chooser.h>
-#include "marshal.h"
 
-#define AGENT_PATH "/org/bluez/agent/sendto"
+#define OBEX_SERVICE	"org.bluez.obex"
+#define OBEX_PATH	"/org/bluez/obex"
+#define TRANSFER_IFACE	"org.bluez.obex.Transfer1"
+#define OPP_IFACE	"org.bluez.obex.ObjectPush1"
+#define CLIENT_IFACE	"org.bluez.obex.Client1"
 
 #define RESPONSE_RETRY 1
 
-static DBusGConnection *conn = NULL;
-static ObexAgent *agent = NULL;
-static DBusGProxy *client_proxy = NULL;
+static GDBusConnection *conn = NULL;
+static GDBusProxy *client_proxy = NULL;
+static GDBusProxy *session = NULL;
+static GDBusProxy *current_transfer = NULL;
+static GCancellable *cancellable = NULL;
 
 static GtkWidget *dialog;
 static GtkWidget *label_from;
@@ -58,7 +60,6 @@ static gchar *option_device = NULL;
 static gchar *option_device_name = NULL;
 static gchar **option_files = NULL;
 
-static DBusGProxy *current_transfer = NULL;
 static guint64 current_size = 0;
 static guint64 total_size = 0;
 static guint64 total_sent = 0;
@@ -69,64 +70,264 @@ static int file_index = 0;
 static gint64 first_update = 0;
 static gint64 last_update = 0;
 
-static void send_notify(DBusGProxy *proxy, DBusGProxyCall *call, void *user_data);
-
-/* Agent callbacks */
-static gboolean release_callback(DBusGMethodInvocation *context, gpointer user_data);
-static gboolean request_callback(DBusGMethodInvocation *context, DBusGProxy *transfer, gpointer user_data);
-static gboolean progress_callback(DBusGMethodInvocation *context,
-				  DBusGProxy *transfer,
-				  guint64 transferred,
-				  gpointer user_data);
-static gboolean complete_callback(DBusGMethodInvocation *context, DBusGProxy *transfer, gpointer user_data);
-static gboolean error_callback(DBusGMethodInvocation *context,
-			       DBusGProxy *transfer,
-			       const char *message,
-			       gpointer user_data);
-
-static void value_free(GValue *value)
+static void on_transfer_properties (GVariant *props);
+static void on_transfer_progress (guint64 transferred);
+static void on_transfer_complete (void);
+static void on_transfer_error (void);
+
+static gint64
+get_system_time (void)
 {
-	g_value_unset(value);
-	g_free(value);
+	struct timeval tmp;
+
+	gettimeofday(&tmp, NULL);
+
+	return (gint64) tmp.tv_usec +
+		(gint64) tmp.tv_sec * G_GINT64_CONSTANT(1000000);
 }
 
-static GHashTable *
-send_files (void)
+static void
+update_from_label (void)
+{
+	char *filename = option_files[file_index];
+	GFile *file, *dir;
+	char *text, *markup;
+
+	file = g_file_new_for_path (filename);
+	dir = g_file_get_parent (file);
+	g_object_unref (file);
+	if (g_file_has_uri_scheme (dir, "file") != FALSE) {
+		text = g_file_get_path (dir);
+	} else {
+		text = g_file_get_uri (dir);
+	}
+	markup = g_markup_escape_text (text, -1);
+	g_free (text);
+	g_object_unref (dir);
+	gtk_label_set_markup (GTK_LABEL (label_from), markup);
+	g_free (markup);
+}
+
+static void
+set_response_visible (GtkDialog *dialog,
+		      int response_id,
+		      gboolean visible)
 {
-	GHashTable *hash;
-	GValue *value;
+	GtkWidget *widget;
 
-	hash = g_hash_table_new_full(g_str_hash, g_str_equal,
-				     g_free, (GDestroyNotify) value_free);
+	widget = gtk_dialog_get_widget_for_response (dialog, response_id);
+	gtk_widget_set_no_show_all (widget, TRUE);
+	gtk_widget_set_visible (widget, visible);
+}
 
-	value = g_new0(GValue, 1);
-	g_value_init(value, G_TYPE_STRING);
-	g_value_set_string(value, option_device);
-	g_hash_table_insert(hash, g_strdup("Destination"), value);
+static void
+handle_error (GError *error)
+{
+	const char *message;
 
-	dbus_g_proxy_begin_call(client_proxy, "SendFiles",
-				send_notify, NULL, NULL,
-				dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), hash,
-				G_TYPE_STRV, option_files,
-				DBUS_TYPE_G_OBJECT_PATH, AGENT_PATH,
-				G_TYPE_INVALID);
+	if (!error || *error->message == '\0')
+		message = _("An unknown error occurred");
+	else
+		message = error->message;
+	gtk_widget_show (image_status);
+	gtk_label_set_markup (GTK_LABEL (label_status), message);
+	g_clear_error (&error);
+
+	/* Clear the progress bar as it may be saying 'Connecting' or
+	 * 'Sending file 1 of 1' which is not true. */
+	gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress), "");
 
-	return hash;
+	set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL, TRUE);
+	set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, FALSE);
+	set_response_visible (GTK_DIALOG (dialog), RESPONSE_RETRY, TRUE);
 }
 
 static void
-setup_agent (void)
+transfer_properties_changed (GDBusProxy *proxy,
+			     GVariant *changed_properties,
+			     GStrv invalidated_properties,
+			     gpointer user_data)
 {
-	if (agent == NULL)
-		agent = obex_agent_new();
+	GVariantIter iter;
+	const char *key;
+	GVariant *value;
+
+	g_variant_iter_init (&iter, changed_properties);
+	while (g_variant_iter_next (&iter, "{&sv}", &key, &value)) {
+		if (g_str_equal (key, "Status")) {
+			const char *status;
+
+			status = g_variant_get_string (value, NULL);
+
+			if (g_str_equal (status, "complete")) {
+				on_transfer_complete ();
+			} else if (g_str_equal (status, "error")) {
+				on_transfer_error ();
+			}
+		} else if (g_str_equal (key, "Transferred")) {
+			guint64 transferred = g_variant_get_uint64 (value);
+
+			on_transfer_progress (transferred);
+		}
 
-	obex_agent_set_release_func(agent, release_callback, NULL);
-	obex_agent_set_request_func(agent, request_callback, NULL);
-	obex_agent_set_progress_func(agent, progress_callback, NULL);
-	obex_agent_set_complete_func(agent, complete_callback, NULL);
-	obex_agent_set_error_func(agent, error_callback, NULL);
+		g_variant_unref (value);
+	}
+}
+
+static void
+transfer_proxy (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
+{
+	GError *error = NULL;
+
+	current_transfer = g_dbus_proxy_new_finish (res, &error);
+
+	if (current_transfer == NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			g_error_free (error);
+			return;
+		}
+
+		handle_error (error);
+		return;
+	}
 
-	obex_agent_setup(agent, AGENT_PATH);
+	g_signal_connect (G_OBJECT (current_transfer), "g-properties-changed",
+		G_CALLBACK (transfer_properties_changed), NULL);
+}
+
+static void
+transfer_created (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
+{
+	GError *error = NULL;
+	GVariant *variant, *properties;
+	const char *transfer;
+
+	variant = g_dbus_proxy_call_finish (proxy, res, &error);
+
+	if (variant == NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			g_error_free (error);
+			return;
+		}
+
+		handle_error (error);
+		return;
+	}
+
+	gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress), NULL);
+
+	first_update = get_system_time ();
+
+	g_variant_get (variant, "(&o@a{sv})", &transfer, &properties);
+
+	on_transfer_properties (properties);
+
+	g_dbus_proxy_new (conn,
+			  G_DBUS_PROXY_FLAGS_NONE,
+			  NULL,
+			  OBEX_SERVICE,
+			  transfer,
+			  TRANSFER_IFACE,
+			  cancellable,
+			  (GAsyncReadyCallback) transfer_proxy,
+			  NULL);
+
+	g_variant_unref (properties);
+	g_variant_unref (variant);
+}
+
+static void
+send_next_file (void)
+{
+	update_from_label ();
+
+	g_dbus_proxy_call (session,
+			   "SendFile",
+			   g_variant_new ("(s)", option_files[file_index]),
+			   G_DBUS_CALL_FLAGS_NONE,
+			   -1,
+			   cancellable,
+			   (GAsyncReadyCallback) transfer_created,
+			   NULL);
+}
+
+static void
+session_proxy (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
+{
+	GError *error = NULL;
+
+	g_clear_object (&session);
+	session = g_dbus_proxy_new_finish (res, &error);
+
+	if (session == NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			g_error_free (error);
+			return;
+		}
+
+		handle_error (error);
+		return;
+	}
+
+	send_next_file ();
+}
+
+static void
+session_created (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
+{
+	GError *error = NULL;
+	GVariant *variant;
+	const char *session;
+
+	variant = g_dbus_proxy_call_finish (proxy, res, &error);
+
+	if (variant == NULL) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+			g_error_free (error);
+			return;
+		}
+
+		handle_error (error);
+		return;
+	}
+
+	g_variant_get (variant, "(&o)", &session);
+
+	g_dbus_proxy_new (conn,
+			  G_DBUS_PROXY_FLAGS_NONE,
+			  NULL,
+			  OBEX_SERVICE,
+			  session,
+			  OPP_IFACE,
+			  cancellable,
+			  (GAsyncReadyCallback) session_proxy,
+			  NULL);
+
+	g_variant_unref (variant);
+}
+
+static void
+send_files (void)
+{
+	GVariant *parameters;
+	GVariantBuilder *builder;
+
+	builder = g_variant_builder_new (G_VARIANT_TYPE_DICTIONARY);
+	g_variant_builder_add (builder, "{sv}", "Target",
+						g_variant_new_string ("opp"));
+
+	parameters = g_variant_new ("(sa{sv})", option_device, builder);
+
+	g_dbus_proxy_call (client_proxy,
+			   "CreateSession",
+			   parameters,
+			   G_DBUS_CALL_FLAGS_NONE,
+			   -1,
+			   cancellable,
+			   (GAsyncReadyCallback) session_created,
+			   NULL);
+
+	g_variant_builder_unref (builder);
 }
 
 static gchar *filename_to_path(const gchar *filename)
@@ -141,16 +342,6 @@ static gchar *filename_to_path(const gchar *filename)
 	return path;
 }
 
-static gint64 get_system_time(void)
-{
-	struct timeval tmp;
-
-	gettimeofday(&tmp, NULL);
-
-	return (gint64) tmp.tv_usec +
-			(gint64) tmp.tv_sec * G_GINT64_CONSTANT(1000000);
-}
-
 static gchar *format_time(gint seconds)
 {
 	gint hours, minutes;
@@ -189,24 +380,10 @@ static gchar *format_time(gint seconds)
 				"approximately %'d hours", hours), hours);
 }
 
-static void
-set_response_visible (GtkDialog *dialog,
-		      int response_id,
-		      gboolean visible)
-{
-	GtkWidget *widget;
-
-	widget = gtk_dialog_get_widget_for_response (dialog, response_id);
-	gtk_widget_set_no_show_all (widget, TRUE);
-	gtk_widget_set_visible (widget, visible);
-}
-
 static void response_callback(GtkWidget *dialog,
 					gint response, gpointer user_data)
 {
 	if (response == RESPONSE_RETRY) {
-		setup_agent ();
-
 		/* Reset buttons */
 		set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, FALSE);
 		set_response_visible (GTK_DIALOG (dialog), RESPONSE_RETRY, FALSE);
@@ -214,16 +391,31 @@ static void response_callback(GtkWidget *dialog,
 
 		/* Reset status and progress bar */
 		gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress),
-					  _("Connecting..."));
+					  _("Connecting…"));
 		gtk_label_set_text (GTK_LABEL (label_status), "");
 		gtk_widget_hide (image_status);
-		send_files ();
+
+		/* If we have a session, we don't need to create another one. */
+		if (session)
+			send_next_file ();
+		else
+			send_files ();
+
 		return;
 	}
 
+	/* Cancel any ongoing dbus calls we may have */
+	g_cancellable_cancel (cancellable);
+
 	if (current_transfer != NULL) {
-		obex_agent_set_error_func(agent, NULL, NULL);
-		dbus_g_proxy_call_no_reply (current_transfer, "Cancel", G_TYPE_INVALID);
+		g_dbus_proxy_call (current_transfer,
+				   "Cancel",
+				   NULL,
+				   G_DBUS_CALL_FLAGS_NONE,
+				   -1,
+				   NULL,
+				   (GAsyncReadyCallback) NULL,
+				   NULL);
 		g_object_unref (current_transfer);
 		current_transfer = NULL;
 	}
@@ -232,13 +424,6 @@ static void response_callback(GtkWidget *dialog,
 	gtk_main_quit();
 }
 
-static gboolean is_palm_device(const gchar *bdaddr)
-{
-	return (g_str_has_prefix(bdaddr, "00:04:6B") ||
-			g_str_has_prefix(bdaddr, "00:07:E0") ||
-				g_str_has_prefix(bdaddr, "00:0E:20"));
-}
-
 static void create_window(void)
 {
 	GtkWidget *vbox, *hbox;
@@ -335,37 +520,6 @@ static void create_window(void)
 
 #define OPENOBEX_CONNECTION_FAILED "org.openobex.Error.ConnectionAttemptFailed"
 
-static gchar *get_error_message(GError *error)
-{
-	char *message;
-
-	if (error == NULL)
-		return g_strdup(_("An unknown error occurred"));
-
-	if (error->code != DBUS_GERROR_REMOTE_EXCEPTION) {
-		message = g_strdup(error->message);
-		goto done;
-	}
-
-	if (dbus_g_error_has_name(error, OPENOBEX_CONNECTION_FAILED) == TRUE &&
-					is_palm_device(option_device)) {
-		message = g_strdup(_("Make sure that remote device "
-					"is switched on and that it "
-					"accepts Bluetooth connections"));
-		goto done;
-	}
-
-	if (*error->message == '\0')
-		message = g_strdup(_("An unknown error occurred"));
-	else
-		message = g_strdup(error->message);
-
-done:
-	g_error_free(error);
-
-	return message;
-}
-
 static gchar *get_device_name(const gchar *address)
 {
 	BluetoothClient *client;
@@ -407,44 +561,18 @@ static gchar *get_device_name(const gchar *address)
 	return found_name;
 }
 
-static void get_properties_callback (DBusGProxy *proxy,
-				     DBusGProxyCall *call,
-				     void *user_data)
+static void
+on_transfer_properties (GVariant *props)
 {
-	GError *error = NULL;
-	gchar *filename = option_files[file_index];
-	GFile *file, *dir;
-	gchar *basename, *text, *markup;
-	GHashTable *hash;
-
-	if (dbus_g_proxy_end_call (proxy, call, &error,
-				   dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &hash,
-				   G_TYPE_INVALID) != FALSE) {
-		GValue *value;
-
-		value = g_hash_table_lookup(hash, "Size");
-		if (value) {
-			current_size = g_value_get_uint64(value);
-
-			last_update = get_system_time();
-		}
-
-		g_hash_table_destroy(hash);
-	}
-
-	file = g_file_new_for_path (filename);
-	dir = g_file_get_parent (file);
-	g_object_unref (file);
-	if (g_file_has_uri_scheme (dir, "file") != FALSE) {
-		text = g_file_get_path (dir);
-	} else {
-		text = g_file_get_uri (dir);
+	char *filename = option_files[file_index];
+	char *basename, *text, *markup;
+	GVariant *size;
+
+	size = g_variant_lookup_value (props, "Size", G_VARIANT_TYPE_UINT64);
+	if (size) {
+		current_size = g_variant_get_uint64 (size);
+		last_update = get_system_time ();
 	}
-	markup = g_markup_escape_text (text, -1);
-	g_free (text);
-	g_object_unref (dir);
-	gtk_label_set_markup(GTK_LABEL(label_from), markup);
-	g_free(markup);
 
 	basename = g_path_get_basename(filename);
 	text = g_strdup_printf(_("Sending %s"), basename);
@@ -460,25 +588,8 @@ static void get_properties_callback (DBusGProxy *proxy,
 	g_free(text);
 }
 
-static gboolean request_callback(DBusGMethodInvocation *context,
-				DBusGProxy *transfer, gpointer user_data)
-{
-	g_assert (current_transfer == NULL);
-
-	dbus_g_proxy_begin_call(transfer, "GetProperties",
-				get_properties_callback, NULL, NULL,
-				G_TYPE_INVALID);
-
-	current_transfer = g_object_ref (transfer);
-
-	dbus_g_method_return(context, "");
-
-	return TRUE;
-}
-
-static gboolean progress_callback(DBusGMethodInvocation *context,
-				DBusGProxy *transfer, guint64 transferred,
-							gpointer user_data)
+static void
+on_transfer_progress (guint64 transferred)
 {
 	gint64 current_time;
 	gint elapsed_time;
@@ -499,24 +610,24 @@ static gboolean progress_callback(DBusGMethodInvocation *context,
 	elapsed_time = (current_time - first_update) / 1000000;
 
 	if (current_time < last_update + 1000000)
-		goto done;
+		return;
 
 	last_update = current_time;
 
 	if (elapsed_time == 0)
-		goto done;
+		return;
 
 	transfer_rate = current_sent / elapsed_time;
 
 	if (transfer_rate == 0)
-		goto done;
+		return;
 
 	remaining_time = (total_size - current_sent) / transfer_rate;
 
 	time = format_time(remaining_time);
 
 	if (transfer_rate >= 3000)
-		rate = g_strdup_printf(_("%d KB/s"), transfer_rate / 1000);
+		rate = g_strdup_printf(_("%d kB/s"), transfer_rate / 1000);
 	else
 		rate = g_strdup_printf(_("%d B/s"), transfer_rate);
 
@@ -528,15 +639,10 @@ static gboolean progress_callback(DBusGMethodInvocation *context,
 	g_free(time);
 	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), text);
 	g_free(text);
-
-done:
-	dbus_g_method_return(context);
-
-	return TRUE;
 }
 
-static gboolean complete_callback(DBusGMethodInvocation *context,
-				DBusGProxy *transfer, gpointer user_data)
+static void
+on_transfer_complete (void)
 {
 	total_sent += current_size;
 
@@ -546,37 +652,32 @@ static gboolean complete_callback(DBusGMethodInvocation *context,
 	g_object_unref (current_transfer);
 	current_transfer = NULL;
 
-	if (file_index == file_count)
-		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 1.0);
-
-	dbus_g_method_return(context);
-
-	return TRUE;
-}
-
-static gboolean release_callback(DBusGMethodInvocation *context,
-							gpointer user_data)
-{
-	dbus_g_method_return(context);
-
-	agent = NULL;
+	if (file_index == file_count) {
+		char *complete;
 
-	gtk_label_set_markup(GTK_LABEL(label_status), NULL);
+		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 1.0);
 
-	gtk_widget_destroy(dialog);
+		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "");
 
-	gtk_main_quit();
+		complete = g_strdup_printf (ngettext ("%u transfer complete",
+						      "%u transfers complete",
+						      file_count), file_count);
+		gtk_label_set_text (GTK_LABEL (label_status), complete);
+		g_free (complete);
 
-	return TRUE;
+		set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, TRUE);
+		set_response_visible (GTK_DIALOG (dialog), RESPONSE_RETRY, FALSE);
+		set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL, FALSE);
+	} else {
+		send_next_file ();
+	}
 }
 
-static gboolean error_callback(DBusGMethodInvocation *context,
-			       DBusGProxy *transfer,
-			       const char *message,
-			       gpointer user_data)
+static void
+on_transfer_error (void)
 {
 	gtk_widget_show (image_status);
-	gtk_label_set_markup(GTK_LABEL(label_status), message);
+	gtk_label_set_markup (GTK_LABEL (label_status), _("There was an error"));
 
 	set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL, TRUE);
 	set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, FALSE);
@@ -584,40 +685,6 @@ static gboolean error_callback(DBusGMethodInvocation *context,
 
 	g_object_unref (current_transfer);
 	current_transfer = NULL;
-
-	if (agent != NULL) {
-		obex_agent_set_release_func(agent, NULL, NULL);
-		agent = NULL;
-	}
-
-	dbus_g_method_return(context);
-
-	return TRUE;
-}
-
-static void send_notify(DBusGProxy *proxy,
-				DBusGProxyCall *call, void *user_data)
-{
-	GError *error = NULL;
-
-	if (dbus_g_proxy_end_call(proxy, call, &error,
-						G_TYPE_INVALID) == FALSE) {
-		char *message;
-
-		message = get_error_message(error);
-		gtk_widget_show (image_status);
-		gtk_label_set_markup(GTK_LABEL(label_status), message);
-		g_free (message);
-
-		set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL, TRUE);
-		set_response_visible (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, FALSE);
-		set_response_visible (GTK_DIALOG (dialog), RESPONSE_RETRY, TRUE);
-		return;
-	}
-
-	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), NULL);
-
-	first_update = get_system_time();
 }
 
 static void
@@ -638,11 +705,12 @@ show_browse_dialog (char **device_name)
 	char *bdaddr;
 	int response_id;
 
-	dialog = gtk_dialog_new_with_buttons(_("Select Device to Send To"), NULL,
-					     GTK_DIALOG_NO_SEPARATOR,
-					     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+	dialog = gtk_dialog_new_with_buttons(_("Select device to send to"), NULL,
+					     0,
+					     _("_Cancel"), GTK_RESPONSE_REJECT,
 					     NULL);
-	send_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("Send _To"), GTK_RESPONSE_ACCEPT);
+	gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
+	send_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Send"), GTK_RESPONSE_ACCEPT);
 	image = gtk_image_new_from_icon_name ("document-send", GTK_ICON_SIZE_BUTTON);
 	gtk_button_set_image (GTK_BUTTON (send_button), image);
 	gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
@@ -663,7 +731,7 @@ show_browse_dialog (char **device_name)
 		     NULL);
 	g_signal_connect(selector, "selected-device-changed",
 			 G_CALLBACK(select_device_changed), dialog);
-	gtk_container_add (GTK_CONTAINER (content_area), selector);
+	gtk_box_pack_start (GTK_BOX (content_area), selector, TRUE, TRUE, 0);
 	bluetooth_chooser_start_discovery (BLUETOOTH_CHOOSER (selector));
 
 	bdaddr = NULL;
@@ -686,9 +754,9 @@ show_select_dialog(void)
 
 	dialog = gtk_file_chooser_dialog_new(_("Choose files to send"), NULL,
 				GTK_FILE_CHOOSER_ACTION_OPEN,
-				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-				GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
-
+				_("_Cancel"), GTK_RESPONSE_CANCEL,
+				_("Select"), GTK_RESPONSE_ACCEPT, NULL);
+	gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
 	gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
 
 	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
@@ -713,9 +781,9 @@ show_select_dialog(void)
 
 static GOptionEntry options[] = {
 	{ "device", 0, 0, G_OPTION_ARG_STRING, &option_device,
-				N_("Remote device to use"), "ADDRESS" },
+				N_("Remote device to use"), N_("ADDRESS") },
 	{ "name", 0, 0, G_OPTION_ARG_STRING, &option_device_name,
-				N_("Remote device's name"), NULL },
+				N_("Remote device's name"), N_("NAME") },
 	{ "dest", 0, G_OPTION_FLAG_HIDDEN,
 			G_OPTION_ARG_STRING, &option_device, NULL, NULL },
 	{ G_OPTION_REMAINING, 0, 0,
@@ -734,7 +802,7 @@ int main(int argc, char *argv[])
 
 	error = NULL;
 
-	if (gtk_init_with_args(&argc, &argv, "[FILE...]",
+	if (gtk_init_with_args(&argc, &argv, _("[FILE...]"),
 				options, GETTEXT_PACKAGE, &error) == FALSE) {
 		if (error != NULL) {
 			g_printerr("%s\n", error->message);
@@ -747,6 +815,8 @@ int main(int argc, char *argv[])
 
 	gtk_window_set_default_icon_name("bluetooth");
 
+	cancellable = g_cancellable_new ();
+
 	/* A device name, but no device? */
 	if (option_device == NULL && option_device_name != NULL) {
 		if (option_files != NULL)
@@ -794,35 +864,31 @@ int main(int argc, char *argv[])
 			total_size += st.st_size;
 	}
 
-	conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+	conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 	if (conn == NULL) {
 		if (error != NULL) {
 			g_printerr("Connecting to session bus failed: %s\n",
 							error->message);
 			g_error_free(error);
 		} else
-			g_print("An unknown error occured\n");
+			g_print("An unknown error occurred\n");
 
 		return 1;
 	}
 
-	dbus_g_object_register_marshaller(marshal_VOID__STRING_STRING,
-					G_TYPE_NONE, G_TYPE_STRING,
-					G_TYPE_STRING, G_TYPE_INVALID);
-
-	dbus_g_object_register_marshaller(marshal_VOID__STRING_STRING_UINT64,
-				G_TYPE_NONE, G_TYPE_STRING,
-				G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
-
-	dbus_g_object_register_marshaller(marshal_VOID__UINT64,
-				G_TYPE_NONE, G_TYPE_UINT64, G_TYPE_INVALID);
-
-	dbus_g_object_register_marshaller(marshal_VOID__STRING_STRING_STRING,
-					  G_TYPE_NONE,
-					  DBUS_TYPE_G_OBJECT_PATH,
-					  G_TYPE_STRING,
-					  G_TYPE_STRING,
-					  G_TYPE_INVALID);
+	client_proxy = g_dbus_proxy_new_sync (conn,
+					      G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+					      NULL,
+					      OBEX_SERVICE,
+					      OBEX_PATH,
+					      CLIENT_IFACE,
+					      cancellable,
+					      &error);
+	if (client_proxy == NULL) {
+		g_printerr("Acquiring proxy failed: %s\n", error->message);
+		g_error_free (error);
+		return 1;
+	}
 
 	if (option_device_name == NULL)
 		option_device_name = get_device_name(option_device);
@@ -831,18 +897,18 @@ int main(int argc, char *argv[])
 
 	create_window();
 
-	client_proxy = dbus_g_proxy_new_for_name(conn, "org.openobex.client",
-					"/", "org.openobex.Client");
-
-	setup_agent ();
-
-	send_files ();
+	if (!g_cancellable_is_cancelled (cancellable))
+		send_files ();
 
 	gtk_main();
 
-	g_object_unref(client_proxy);
+	g_cancellable_cancel (cancellable);
 
-	dbus_g_connection_unref(conn);
+	g_clear_object (&cancellable);
+	g_clear_object (&current_transfer);
+	g_clear_object (&session);
+	g_object_unref (client_proxy);
+	g_object_unref (conn);
 
 	g_strfreev(option_files);
 	g_free(option_device);
diff --git a/sendto/obex-agent.c b/sendto/obex-agent.c
new file mode 100644
index 0000000..101476f
--- /dev/null
+++ b/sendto/obex-agent.c
@@ -0,0 +1,455 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2005-2008  Marcel Holtmann <marcel holtmann org>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <gio/gio.h>
+
+#include "obex-agent.h"
+
+#ifdef DEBUG
+#define DBG(fmt, arg...) printf("%s:%s() " fmt "\n", __FILE__, __FUNCTION__ , ## arg)
+#else
+#define DBG(fmt...)
+#endif
+
+#define OBEX_SERVICE	"org.openobex.client"
+
+#define OBEX_CLIENT_PATH	"/"
+#define OBEX_CLIENT_INTERFACE	"org.openobex.Client"
+#define OBEX_TRANSFER_INTERFACE	"org.openobex.Transfer"
+
+static const gchar introspection_xml[] =
+"<node name='%s'>"
+"  <interface name='org.openobex.Agent'>"
+"    <method name='Request'>"
+"      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
+"      <arg type='o' name='transfer' direction='in'/>"
+"      <arg type='s' name='name' direction='out'/>"
+"    </method>"
+""
+"    <method name='Progress'>"
+"      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
+"      <arg type='o' name='transfer' direction='in'/>"
+"      <arg type='t' name='transferred' direction='in'/>"
+"    </method>"
+""
+"    <method name='Complete'>"
+"      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
+"      <arg type='o' name='transfer' direction='in'/>"
+"    </method>"
+""
+"    <method name='Release'>"
+"      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
+"    </method>"
+""
+"    <method name='Error'>"
+"      <annotation name='org.freedesktop.DBus.GLib.Async' value=''/>"
+"      <arg type='o' name='transfer' direction='in'/>"
+"      <arg type='s' name='message' direction='in'/>"
+"    </method>"
+"  </interface>"
+"</node>";
+
+#define OBEX_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
+					OBEX_TYPE_AGENT, ObexAgentPrivate))
+
+typedef struct _ObexAgentPrivate ObexAgentPrivate;
+
+struct _ObexAgentPrivate {
+	GDBusConnection *conn;
+	gchar *busname;
+	gchar *path;
+	GDBusNodeInfo *introspection_data;
+	guint reg_id;
+	guint watch_id;
+
+	ObexAgentReleaseFunc release_func;
+	gpointer release_data;
+
+	ObexAgentRequestFunc request_func;
+	gpointer request_data;
+
+	ObexAgentProgressFunc progress_func;
+	gpointer progress_data;
+
+	ObexAgentCompleteFunc complete_func;
+	gpointer complete_data;
+
+	ObexAgentErrorFunc error_func;
+	gpointer error_data;
+};
+
+G_DEFINE_TYPE(ObexAgent, obex_agent, G_TYPE_OBJECT)
+
+static GDBusProxy *
+get_proxy_from_path (ObexAgent *agent,
+		     const char *path)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE (agent);
+
+	return g_dbus_proxy_new_sync (priv->conn,
+				      G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+				      NULL,
+				      OBEX_SERVICE,
+				      path,
+				      OBEX_TRANSFER_INTERFACE,
+				      NULL,
+				      NULL);
+
+}
+
+static gboolean obex_agent_request(ObexAgent *agent, const char *path,
+						GDBusMethodInvocation *invocation)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	if (priv->request_func) {
+		GDBusProxy *proxy;
+
+		proxy = get_proxy_from_path (agent, path);
+
+		priv->request_func (invocation, proxy, priv->request_data);
+
+		g_object_unref(proxy);
+	} else {
+		g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", ""));
+	}
+
+	return TRUE;
+}
+
+static gboolean obex_agent_progress(ObexAgent *agent, const char *path,
+			guint64 transferred, GDBusMethodInvocation *invocation)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+	gboolean result = FALSE;
+
+	DBG("agent %p", agent);
+
+	if (priv->progress_func) {
+		GDBusProxy *proxy;
+
+		proxy = get_proxy_from_path (agent, path);
+
+		result = priv->progress_func(invocation, proxy, transferred,
+							priv->progress_data);
+
+		g_object_unref(proxy);
+	} else {
+		g_dbus_method_invocation_return_value (invocation, NULL);
+	}
+
+	return result;
+}
+
+static gboolean obex_agent_complete(ObexAgent *agent, const char *path,
+						GDBusMethodInvocation *invocation)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+	gboolean result = FALSE;
+
+	DBG("agent %p", agent);
+
+	if (priv->complete_func) {
+		GDBusProxy *proxy;
+
+		proxy = get_proxy_from_path (agent, path);
+
+		result = priv->complete_func(invocation, proxy,
+						priv->complete_data);
+
+		g_object_unref(proxy);
+	} else {
+		g_dbus_method_invocation_return_value (invocation, NULL);
+	}
+
+	return result;
+}
+
+static gboolean obex_agent_release(ObexAgent *agent,
+						GDBusMethodInvocation *invocation)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+	gboolean result = FALSE;
+
+	DBG("agent %p", agent);
+
+	if (priv->release_func)
+		result = priv->release_func(invocation, priv->release_data);
+	else
+		g_dbus_method_invocation_return_value (invocation, NULL);
+
+	g_object_unref(agent);
+
+	return result;
+}
+
+static gboolean obex_agent_error(ObexAgent *agent,
+				 const char *path,
+				 const char *message,
+				 GDBusMethodInvocation *invocation)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+	gboolean result = FALSE;
+
+	DBG("agent %p", agent);
+
+	if (priv->error_func) {
+		GDBusProxy *proxy;
+
+		proxy = get_proxy_from_path (agent, path);
+
+		result = priv->error_func(invocation, proxy, message,
+							priv->progress_data);
+
+		g_object_unref(proxy);
+	} else {
+		g_dbus_method_invocation_return_value (invocation, NULL);
+	}
+
+	return result;
+}
+
+static void
+name_appeared_cb (GDBusConnection *connection,
+		  const gchar     *name,
+		  const gchar     *name_owner,
+		  ObexAgent       *agent)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	g_free (priv->busname);
+	priv->busname = g_strdup (name_owner);
+}
+
+static void
+name_vanished_cb (GDBusConnection *connection,
+		  const gchar     *name,
+		  ObexAgent       *agent)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	g_free (priv->busname);
+	priv->busname = NULL;
+}
+
+static void obex_agent_init(ObexAgent *agent)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	priv->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+	priv->watch_id = g_bus_watch_name_on_connection (priv->conn,
+							 OBEX_SERVICE,
+							 G_BUS_NAME_WATCHER_FLAGS_NONE,
+							 (GBusNameAppearedCallback) name_appeared_cb,
+							 (GBusNameVanishedCallback) name_vanished_cb,
+							 agent,
+							 NULL);
+}
+
+static void obex_agent_finalize(GObject *agent)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	g_bus_unwatch_name (priv->watch_id);
+	g_free (priv->busname);
+	g_free(priv->path);
+	g_dbus_node_info_unref (priv->introspection_data);
+	g_object_unref (priv->conn);
+
+	G_OBJECT_CLASS(obex_agent_parent_class)->finalize(agent);
+}
+
+static void obex_agent_class_init(ObexAgentClass *klass)
+{
+	GObjectClass *object_class = (GObjectClass *) klass;
+
+	DBG("class %p", klass);
+
+	g_type_class_add_private(klass, sizeof(ObexAgentPrivate));
+
+	object_class->finalize = obex_agent_finalize;
+}
+
+ObexAgent *obex_agent_new(void)
+{
+	ObexAgent *agent;
+
+	agent = OBEX_AGENT(g_object_new(OBEX_TYPE_AGENT, NULL));
+
+	DBG("agent %p", agent);
+
+	return agent;
+}
+
+static void
+handle_method_call (GDBusConnection       *connection,
+		    const gchar           *sender,
+		    const gchar           *object_path,
+		    const gchar           *interface_name,
+		    const gchar           *method_name,
+		    GVariant              *parameters,
+		    GDBusMethodInvocation *invocation,
+		    gpointer               user_data)
+{
+	ObexAgent *agent = (ObexAgent *) user_data;
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	if (g_str_equal (sender, priv->busname) == FALSE) {
+		g_assert_not_reached ();
+		/* FIXME, should this just be a D-Bus Error instead? */
+	}
+
+	if (g_strcmp0 (method_name, "Request") == 0) {
+		char *path;
+		g_variant_get (parameters, "(o)", &path);
+		obex_agent_request (agent, path, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "Progress") == 0) {
+		char *path;
+		guint64 transferred;
+		g_variant_get (parameters, "(ot)", &path, &transferred);
+		obex_agent_progress (agent, path, transferred, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "Complete") == 0) {
+		char *path;
+		g_variant_get (parameters, "(o)", &path);
+		obex_agent_complete (agent, path, invocation);
+		g_free (path);
+	} else if (g_strcmp0 (method_name, "Error") == 0) {
+		char *path, *message;
+		g_variant_get (parameters, "(os)", &path, &message);
+		obex_agent_error (agent, path, message, invocation);
+		g_free (path);
+		g_free (message);
+	} else if (g_strcmp0 (method_name, "Release") == 0) {
+		obex_agent_release (agent, invocation);
+	}
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+	handle_method_call,
+	NULL, /* GetProperty */
+	NULL, /* SetProperty */
+};
+
+gboolean obex_agent_setup(ObexAgent *agent, const char *path)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+	GError *error = NULL;
+
+	DBG("agent %p path %s", agent, path);
+
+	if (priv->path != NULL) {
+		g_warning ("Obex Agent already setup on '%s'", priv->path);
+		return FALSE;
+	}
+
+	priv->path = g_strdup (path);
+
+	char *xml;
+	xml = g_strdup_printf (introspection_xml, path);
+	priv->introspection_data = g_dbus_node_info_new_for_xml (xml, NULL);
+	g_free (xml);
+	g_assert (priv->introspection_data);
+
+	priv->reg_id = g_dbus_connection_register_object (priv->conn,
+						      priv->path,
+						      priv->introspection_data->interfaces[0],
+						      &interface_vtable,
+						      agent,
+						      NULL,
+						      &error);
+	if (priv->reg_id == 0) {
+		g_warning ("Failed to register object: %s", error->message);
+		g_error_free (error);
+	}
+
+	return TRUE;
+}
+
+void obex_agent_set_release_func(ObexAgent *agent,
+				ObexAgentReleaseFunc func, gpointer data)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	priv->release_func = func;
+	priv->release_data = data;
+}
+
+void obex_agent_set_request_func(ObexAgent *agent,
+				ObexAgentRequestFunc func, gpointer data)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	priv->request_func = func;
+	priv->request_data = data;
+}
+
+void obex_agent_set_progress_func(ObexAgent *agent,
+				ObexAgentProgressFunc func, gpointer data)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	priv->progress_func = func;
+	priv->progress_data = data;
+}
+
+void obex_agent_set_complete_func(ObexAgent *agent,
+				ObexAgentCompleteFunc func, gpointer data)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	priv->complete_func = func;
+	priv->complete_data = data;
+}
+
+void obex_agent_set_error_func(ObexAgent *agent,
+			       ObexAgentErrorFunc func, gpointer data)
+{
+	ObexAgentPrivate *priv = OBEX_AGENT_GET_PRIVATE(agent);
+
+	DBG("agent %p", agent);
+
+	priv->error_func = func;
+	priv->error_data = data;
+}
diff --git a/sendto/obex-agent.h b/sendto/obex-agent.h
new file mode 100644
index 0000000..d2a9e1f
--- /dev/null
+++ b/sendto/obex-agent.h
@@ -0,0 +1,87 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __OBEX_AGENT_H
+#define __OBEX_AGENT_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define OBEX_TYPE_AGENT (obex_agent_get_type())
+#define OBEX_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+						OBEX_TYPE_AGENT, ObexAgent))
+#define OBEX_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
+					OBEX_TYPE_AGENT, ObexAgentClass))
+#define OBEX_IS_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+							OBEX_TYPE_AGENT))
+#define OBEX_IS_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \
+							OBEX_TYPE_AGENT))
+#define OBEX_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
+					OBEX_TYPE_AGENT, ObexAgentClass))
+
+typedef struct _ObexAgent ObexAgent;
+typedef struct _ObexAgentClass ObexAgentClass;
+
+struct _ObexAgent {
+	GObject parent;
+};
+
+struct _ObexAgentClass {
+	GObjectClass parent_class;
+};
+
+GType obex_agent_get_type(void);
+
+ObexAgent *obex_agent_new(void);
+
+gboolean obex_agent_setup(ObexAgent *agent, const char *path);
+
+typedef gboolean (*ObexAgentReleaseFunc) (GDBusMethodInvocation *context,
+								gpointer data);
+typedef gboolean (*ObexAgentRequestFunc) (GDBusMethodInvocation *context,
+					GDBusProxy *transfer, gpointer data);
+typedef gboolean (*ObexAgentProgressFunc) (GDBusMethodInvocation *context,
+					GDBusProxy *transfer,
+					guint64 transferred, gpointer data);
+typedef gboolean (*ObexAgentCompleteFunc) (GDBusMethodInvocation *context,
+					GDBusProxy *transfer, gpointer data);
+typedef gboolean (*ObexAgentErrorFunc) (GDBusMethodInvocation *context,
+					GDBusProxy *transfer,
+					const char *message,
+					gpointer data);
+
+void obex_agent_set_release_func(ObexAgent *agent,
+				ObexAgentReleaseFunc func, gpointer data);
+void obex_agent_set_request_func(ObexAgent *agent,
+				ObexAgentRequestFunc func, gpointer data);
+void obex_agent_set_progress_func(ObexAgent *agent,
+				ObexAgentProgressFunc func, gpointer data);
+void obex_agent_set_complete_func(ObexAgent *agent,
+				ObexAgentCompleteFunc func, gpointer data);
+void obex_agent_set_error_func(ObexAgent *agent,
+			       ObexAgentErrorFunc func, gpointer data);
+G_END_DECLS
+
+#endif /* __OBEX_AGENT_H */
diff --git a/wizard/Makefile.am b/wizard/Makefile.am
index ec66cf1..09ed1d3 100644
--- a/wizard/Makefile.am
+++ b/wizard/Makefile.am
@@ -11,7 +11,7 @@ bin_PROGRAMS = mate-bluetooth-wizard
 
 mate_bluetooth_wizard_SOURCES = main.c
 
-mate_bluetooth_wizard_LDADD = $(top_builddir)/lib/libmate-bluetooth.la $(top_builddir)/lib/libcommon.la libwizard.la $(WIZARD_LIBS)
+mate_bluetooth_wizard_LDADD = $(top_builddir)/lib/libmate-bluetooth.la libwizard.la $(WIZARD_LIBS)
 
 test_input_SOURCES = test-input.c bluetooth-input.c bluetooth-input.h
 test_input_LDADD = $(INPUT_LIBS)
diff --git a/wizard/main.c b/wizard/main.c
index 25d24ad..afb960c 100644
--- a/wizard/main.c
+++ b/wizard/main.c
@@ -29,8 +29,8 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
+#include <gio/gio.h>
 
-#include <dbus/dbus-glib.h>
 #include <unique/uniqueapp.h>
 
 #include <bluetooth-client.h>
@@ -41,7 +41,7 @@
 
 #include "pin.h"
 
-#define AGENT_PATH "/org/bluez/agent/wizard"
+#define AGENT_PATH "/org/mate/agent/wizard"
 
 /* We'll try to connect to the device repeatedly for that
  * amount of time before we bail out */
@@ -65,6 +65,9 @@ static gboolean set_page_search_complete(void);
 static BluetoothClient *client;
 static BluetoothAgent *agent;
 
+static GCancellable *cancellable = NULL;
+
+static GDBusProxy *target_proxy = NULL;
 static gchar *target_address = NULL;
 static gchar *target_name = NULL;
 static gchar *target_pincode = NULL;
@@ -153,19 +156,18 @@ update_random_pincode (void)
 	user_pincode = NULL;
 }
 
-static gboolean
-pincode_callback (DBusGMethodInvocation *context,
-		  DBusGProxy *device,
-		  gpointer user_data)
+static void
+pincode_callback (GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  gpointer               user_data)
 {
 	target_ssp = FALSE;
 
 	/* Only show the pincode page if the pincode isn't automatic */
 	if (automatic_pincode == FALSE)
 		gtk_assistant_set_current_page (window_assistant, PAGE_SETUP);
-	dbus_g_method_return(context, pincode);
-
-	return TRUE;
+	g_dbus_method_invocation_return_value (invocation,
+						       g_variant_new ("(s)", pincode));
 }
 
 void
@@ -174,13 +176,6 @@ restart_button_clicked (GtkButton *button,
 {
 	/* Clean up old state */
 	update_random_pincode ();
-	target_ssp = FALSE;
-	target_type = BLUETOOTH_TYPE_ANY;
-	display_called = FALSE;
-	g_free (target_address);
-	target_address = NULL;
-	g_free (target_name);
-	target_name = NULL;
 
 	g_object_set (selector,
 		      "device-category-filter", BLUETOOTH_CATEGORY_NOT_PAIRED_OR_TRUSTED,
@@ -193,7 +188,7 @@ void
 does_not_match_cb (GtkButton *button,
 		   gpointer user_data)
 {
-	DBusGMethodInvocation *context;
+	GDBusMethodInvocation *context;
 	GError *error = NULL;
 	char *text;
 
@@ -208,9 +203,9 @@ does_not_match_cb (GtkButton *button,
 	g_free(text);
 
 	context = g_object_get_data (G_OBJECT (button), "context");
-	g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
-		    "Agent callback cancelled");
-	dbus_g_method_return(context, error);
+	error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
+			    "Agent callback cancelled");
+	g_dbus_method_invocation_take_error (context, error);
 
 	g_object_set_data (G_OBJECT(does_not_match_button), "context", NULL);
 	g_object_set_data (G_OBJECT(matches_button), "context", NULL);
@@ -220,22 +215,22 @@ void
 matches_cb (GtkButton *button,
 	    gpointer user_data)
 {
-	DBusGMethodInvocation *context;
+	GDBusMethodInvocation *context;
 
 	context = g_object_get_data (G_OBJECT (button), "context");
 	gtk_widget_set_sensitive (does_not_match_button, FALSE);
 	gtk_widget_set_sensitive (matches_button, FALSE);
-	dbus_g_method_return(context, "");
+	g_dbus_method_invocation_return_value (context, NULL);
 
 	g_object_set_data (G_OBJECT(does_not_match_button), "context", NULL);
 	g_object_set_data (G_OBJECT(matches_button), "context", NULL);
 }
 
-static gboolean
-confirm_callback (DBusGMethodInvocation *context,
-		  DBusGProxy *device,
-		  guint pin,
-		  gpointer user_data)
+static void
+confirm_callback (GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  guint                  pin,
+		  gpointer               user_data)
 {
 	char *str, *label;
 
@@ -253,18 +248,16 @@ confirm_callback (DBusGMethodInvocation *context,
 	set_large_label (GTK_LABEL (label_ssp_pin), str);
 	g_free (str);
 
-	g_object_set_data (G_OBJECT(does_not_match_button), "context", context);
-	g_object_set_data (G_OBJECT(matches_button), "context", context);
-
-	return TRUE;
+	g_object_set_data (G_OBJECT(does_not_match_button), "context", invocation);
+	g_object_set_data (G_OBJECT(matches_button), "context", invocation);
 }
 
-static gboolean
-display_callback (DBusGMethodInvocation *context,
-		  DBusGProxy *device,
-		  guint pin,
-		  guint entered,
-		  gpointer user_data)
+static void
+display_callback (GDBusMethodInvocation *invocation,
+		  GDBusProxy            *device,
+		  guint                  pin,
+		  guint                  entered,
+		  gpointer               user_data)
 {
 	gchar *text, *done, *code;
 
@@ -305,14 +298,12 @@ display_callback (DBusGMethodInvocation *context,
 	g_free(done);
 	g_free(code);
 
-	dbus_g_method_return(context);
-
-	return TRUE;
+	g_dbus_method_invocation_return_value (invocation, NULL);
 }
 
 static gboolean
-cancel_callback (DBusGMethodInvocation *context,
-		 gpointer user_data)
+cancel_callback (GDBusMethodInvocation *invocation,
+		 gpointer               user_data)
 {
 	gchar *text;
 
@@ -328,7 +319,7 @@ cancel_callback (DBusGMethodInvocation *context,
 	gtk_label_set_text(GTK_LABEL(label_failure), text);
 	g_free(text);
 
-	dbus_g_method_return(context);
+	g_dbus_method_invocation_return_value (invocation, NULL);
 
 	return TRUE;
 }
@@ -339,15 +330,24 @@ typedef struct {
 } ConnectData;
 
 static void
-connect_callback (BluetoothClient *_client,
-		  gboolean success,
-		  gpointer user_data)
+connect_callback (GObject      *source_object,
+		  GAsyncResult *res,
+		  gpointer      user_data)
 {
 	ConnectData *data = (ConnectData *) user_data;
+	GError *error = NULL;
+	gboolean success;
 
-	if (success == FALSE && g_timer_elapsed (data->timer, NULL) < CONNECT_TIMEOUT) {
-		if (bluetooth_client_connect_service(client, data->path, connect_callback, data) != FALSE)
+	success = bluetooth_client_connect_service_finish (BLUETOOTH_CLIENT (source_object), res, &error);
+
+	if (success == FALSE) {
+		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
+				g_timer_elapsed (data->timer, NULL) < CONNECT_TIMEOUT) {
+			/* Retry again as long as we still have time and user has not cancelled. */
+			bluetooth_client_connect_service (client, data->path, TRUE, cancellable, connect_callback, data);
 			return;
+		}
+		g_error_free (error);
 	}
 
 	if (success == FALSE)
@@ -361,17 +361,22 @@ connect_callback (BluetoothClient *_client,
 }
 
 static void
-create_callback (BluetoothClient *_client,
-		 const char *path,
-		 const GError *error,
-		 gpointer user_data)
+create_callback (GObject      *source_object,
+		 GAsyncResult *res,
+		 gpointer      user_data)
 {
 	ConnectData *data;
+	GError *error = NULL;
+	gboolean success;
+	gchar *path;
+
+	success = bluetooth_client_setup_device_finish (client,
+						    res, &path, &error);
 
 	create_started = FALSE;
 
 	/* Create failed */
-	if (path == NULL) {
+	if (!success) {
 		char *text;
 
 		gtk_assistant_set_current_page (window_assistant, PAGE_FAILURE);
@@ -386,26 +391,23 @@ create_callback (BluetoothClient *_client,
 		return;
 	}
 
-	bluetooth_client_set_trusted(client, path, TRUE);
+	bluetooth_client_set_trusted (client, path, TRUE);
 
 	data = g_new0 (ConnectData, 1);
 	data->path = g_strdup (path);
 	data->timer = g_timer_new ();
 
-	if (bluetooth_client_connect_service(client, path, connect_callback, data) != FALSE) {
-		gtk_assistant_set_current_page (window_assistant, PAGE_FINISHING);
-	} else {
-		gtk_assistant_set_current_page (window_assistant, PAGE_SUMMARY);
-		g_timer_destroy (data->timer);
-		g_free (data->path);
-		g_free (data);
-	}
+	bluetooth_client_connect_service (client, path, TRUE, cancellable, connect_callback, data);
+
+	gtk_assistant_set_current_page (window_assistant, PAGE_FINISHING);
 }
 
 void
 close_callback (GtkWidget *assistant,
 		gpointer data)
 {
+	g_cancellable_cancel (cancellable);
+
 	gtk_widget_destroy(assistant);
 
 	gtk_main_quit();
@@ -519,8 +521,8 @@ void prepare_callback (GtkWidget *assistant,
 	}
 
 	if ((page == page_setup || page == page_connecting) && (create_started == FALSE)) {
-		const char *path = AGENT_PATH;
 		char *pin_ret;
+		gboolean pair = TRUE;
 
 		/* Set the filter on the selector, so we can use it to get more
 		 * info later, in page_summary */
@@ -531,12 +533,14 @@ void prepare_callback (GtkWidget *assistant,
 		/* Do we pair, or don't we? */
 		pin_ret = get_pincode_for_device (target_type, target_address, target_name, NULL);
 		if (pin_ret != NULL && g_str_equal (pin_ret, "NULL"))
-			path = NULL;
+			pair = FALSE;
 		g_free (pin_ret);
 
 		g_object_ref(agent);
-		bluetooth_client_create_device (client, target_address,
-						path, create_callback, assistant);
+		bluetooth_client_setup_device (client,
+						g_dbus_proxy_get_object_path(target_proxy),
+						pair, cancellable,
+						create_callback, assistant);
 		create_started = TRUE;
 	}
 
@@ -769,6 +773,14 @@ select_device_changed (BluetoothChooser *selector,
 	} else {
 		legacypairing = TRUE;
 	}
+	g_value_unset(&value);
+
+	g_clear_object(&target_proxy);
+	if (bluetooth_chooser_get_selected_device_info (selector, "proxy", &value)) {
+		target_proxy = g_value_dup_object(&value);
+	}
+	g_value_unset(&value);
+	g_warn_if_fail(target_proxy == NULL);
 
 	g_free(target_address);
 	target_address = g_strdup (address);
@@ -1032,14 +1044,21 @@ int main (int argc, char **argv)
 
 	update_random_pincode ();
 
+	cancellable = g_cancellable_new();
+
 	client = bluetooth_client_new();
 
 	agent = bluetooth_agent_new();
 
-	bluetooth_agent_set_pincode_func(agent, pincode_callback, NULL);
-	bluetooth_agent_set_display_func(agent, display_callback, NULL);
-	bluetooth_agent_set_cancel_func(agent, cancel_callback, NULL);
-	bluetooth_agent_set_confirm_func(agent, confirm_callback, NULL);
+	if (bluetooth_agent_register (agent) == FALSE) {
+		g_warning("Agent registration failure");
+		return 1;
+	}
+
+	bluetooth_agent_set_pincode_func (agent, pincode_callback, NULL);
+	bluetooth_agent_set_display_func (agent, display_callback, NULL);
+	bluetooth_agent_set_cancel_func (agent, cancel_callback, NULL);
+	bluetooth_agent_set_confirm_func (agent, confirm_callback, NULL);
 
 	bluetooth_agent_setup(agent, AGENT_PATH);
 
