[gnome-bluetooth] Refactor bluetooth-applet as a library
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-bluetooth] Refactor bluetooth-applet as a library
- Date: Wed, 27 Oct 2010 20:02:41 +0000 (UTC)
commit 1838f070f107adcc2861d518a7ad5bb1b0df7985
Author: Giovanni Campagna <scampa giovanni gmail com>
Date: Wed Sep 29 21:39:53 2010 +0200
Refactor bluetooth-applet as a library
Take out non UI parts of bluetooth-applet and put them in a private
library, which will be used by gnome-shell (and therefore is installed
in gnome-shell private prefix).
https://bugzilla.gnome.org/show_bug.cgi?id=626759
.gitignore | 2 +
applet/Makefile.am | 1 +
applet/lib/Makefile.am | 46 ++
applet/lib/bluetooth-applet.c | 928 +++++++++++++++++++++++++++++++++++++++++
applet/lib/bluetooth-applet.h | 126 ++++++
applet/lib/marshal.list | 3 +
configure.ac | 1 +
7 files changed, 1107 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index b582429..868f66a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,6 +50,8 @@ applet/bluetooth-applet
applet/bluetooth-applet.desktop.in
applet/test-agentdialog
applet/test-icon
+applet/lib/GnomeBluetoothApplet-1.0.gir
+applet/lib/GnomeBluetoothApplet-1.0.typelib
properties/bluetooth-properties
properties/bluetooth-properties.desktop.in
diff --git a/applet/Makefile.am b/applet/Makefile.am
index 3511c2b..dbe7aa9 100644
--- a/applet/Makefile.am
+++ b/applet/Makefile.am
@@ -1,3 +1,4 @@
+SUBDIRS = lib
bin_PROGRAMS = bluetooth-applet
diff --git a/applet/lib/Makefile.am b/applet/lib/Makefile.am
new file mode 100644
index 0000000..b4cd5a9
--- /dev/null
+++ b/applet/lib/Makefile.am
@@ -0,0 +1,46 @@
+CLEANFILES =
+BUILT_SOURCES = marshal.h marshal.c
+
+# This is where private libraries and typelibs for gnome-shell are installed
+# (provided that gnome-bluetooth and gnome-shell are configured with the same
+# libdir)
+gnomeshelldir = $(libdir)/gnome-shell
+
+gnomeshell_LTLIBRARIES = libgnome-bluetooth-applet.la
+
+libgnome_bluetooth_applet_la_SOURCES = \
+ bluetooth-applet.c \
+ bluetooth-applet.h \
+ marshal.c
+
+libgnome_bluetooth_applet_la_LIBADD = $(LIBGNOMEBT_LIBS) $(top_builddir)/lib/libcommon.la
+
+libgnome_bluetooth_applet_la_LDFLAGS = -no-undefined
+
+AM_CFLAGS = -I$(srcdir) -I$(top_srcdir)/lib $(LIBGNOMEBT_CFLAGS) $(COMMON_CFLAGS) $(WARN_CFLAGS) $(DISABLE_DEPRECATED)
+
+marshal.h: marshal.list
+ $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=marshal $< --header > $@
+
+marshal.c: marshal.list
+ $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=marshal $< --header --body > $@
+
+include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+if HAVE_INTROSPECTION
+GnomeBluetoothApplet-1.0.gir: libgnome-bluetooth-applet.la
+GnomeBluetoothApplet_1_0_gir_SCANNERFLAGS = --warn-all --symbol-prefix=bluetooth_ --identifier-prefix=Bluetooth
+GnomeBluetoothApplet_1_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 DBusGLib-1.0 GModule-2.0 GnomeBluetooth-1.0
+GnomeBluetoothApplet_1_0_gir_PACKAGES = gobject-2.0 gtk+-3.0 dbus-glib-1 gmodule-2.0 glib-2.0
+GnomeBluetoothApplet_1_0_gir_CFLAGS = -I$(srcdir) -I$(top_srcdir) -I$(top_srcdir)/lib
+GnomeBluetoothApplet_1_0_gir_LIBS = libgnome-bluetooth-applet.la
+GnomeBluetoothApplet_1_0_gir_FILES = $(libgnome_bluetooth_applet_la_SOURCES)
+INTROSPECTION_GIRS += GnomeBluetoothApplet-1.0.gir
+
+gnomeshell_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES += $(gnomeshell_DATA)
+endif # HAVE_INTROSPECTION
diff --git a/applet/lib/bluetooth-applet.c b/applet/lib/bluetooth-applet.c
new file mode 100644
index 0000000..9ffa3d7
--- /dev/null
+++ b/applet/lib/bluetooth-applet.c
@@ -0,0 +1,928 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ *
+ * 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/gi18n.h>
+#include <gtk/gtk.h>
+#include <dbus/dbus-glib.h>
+
+#include <bluetooth-applet.h>
+#include <lib/bluetooth-client.h>
+#include <lib/bluetooth-client-private.h>
+#include <lib/bluetooth-killswitch.h>
+#include <lib/bluetooth-agent.h>
+
+#include <marshal.h>
+
+static gpointer
+bluetooth_simple_device_copy (gpointer boxed)
+{
+ BluetoothSimpleDevice* origin = (BluetoothSimpleDevice*) boxed;
+
+ BluetoothSimpleDevice* result = g_new (BluetoothSimpleDevice, 1);
+ result->bdaddr = g_strdup (origin->bdaddr);
+ result->device_path = g_strdup (origin->device_path);
+ result->alias = g_strdup (origin->alias);
+ result->connected = origin->connected;
+ result->can_connect = origin->can_connect;
+ result->capabilities = origin->capabilities;
+ result->type = origin->type;
+
+ return (gpointer)result;
+}
+
+static void
+bluetooth_simple_device_free (gpointer boxed)
+{
+ BluetoothSimpleDevice* obj = (BluetoothSimpleDevice*) boxed;
+
+ g_free (obj->device_path);
+ g_free (obj->bdaddr);
+ g_free (obj->alias);
+ g_free (obj);
+}
+
+G_DEFINE_BOXED_TYPE(BluetoothSimpleDevice, bluetooth_simple_device, bluetooth_simple_device_copy, bluetooth_simple_device_free)
+
+struct _BluetoothApplet
+{
+ GObject parent_instance;
+
+ BluetoothKillswitch* killswitch_manager;
+ BluetoothClient* client;
+ GtkTreeModel* client_model;
+ GtkTreeIter* default_adapter;
+ BluetoothAgent* agent;
+ GHashTable* pending_requests;
+
+ gint num_adapters_powered;
+ gint num_adapters_present;
+};
+
+struct _BluetoothAppletClass
+{
+ GObjectClass parent_class;
+
+};
+
+G_DEFINE_TYPE(BluetoothApplet, bluetooth_applet, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_KILLSWITCH_STATE,
+ PROP_DISCOVERABLE,
+ PROP_FULL_MENU,
+ PROP_LAST
+};
+static GParamSpec *properties[PROP_LAST];
+
+enum {
+ SIGNAL_DEVICES_CHANGED,
+
+ SIGNAL_PINCODE_REQUEST,
+ SIGNAL_CONFIRM_REQUEST,
+ SIGNAL_AUTHORIZE_REQUEST,
+ SIGNAL_CANCEL_REQUEST,
+
+ SIGNAL_LAST
+};
+guint signals[SIGNAL_LAST];
+
+/**
+ * bluetooth_applet_agent_reply_passkey:
+ *
+ * @self: a #BluetoothApplet
+ * @request_key: (transfer full): an opaque token given in the pincode-request signal
+ * @passkey: (transfer full) (allow-none): the passkey entered by the user, or NULL if the dialog was dismissed
+ */
+void
+bluetooth_applet_agent_reply_passkey(BluetoothApplet* self, gchar* request_key, gchar* passkey)
+{
+ DBusGMethodInvocation* context;
+
+ g_return_if_fail (BLUETOOTH_IS_APPLET (self));
+ g_return_if_fail (request_key != NULL);
+
+ context = g_hash_table_lookup (self->pending_requests, request_key);
+
+ if (passkey != NULL) {
+ dbus_g_method_return (context, passkey);
+ } else {
+ GError *error;
+ error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
+ "Pairing request rejected");
+ dbus_g_method_return_error (context, error);
+ }
+
+ g_hash_table_remove (self->pending_requests, request_key);
+ g_free (request_key);
+ g_free (passkey);
+}
+
+/**
+ * bluetooth_applet_agent_reply_pincode:
+ *
+ * @self: a #BluetoothApplet
+ * @request_key: (transfer full): an opaque token given in the pincode-request signal
+ * @pincode: the PIN code entered by the user, or -1 if the dialog was dismissed
+ */
+void
+bluetooth_applet_agent_reply_pincode(BluetoothApplet* self, gchar* request_key, gint pincode)
+{
+ DBusGMethodInvocation* context;
+
+ g_return_if_fail (BLUETOOTH_IS_APPLET (self));
+ g_return_if_fail (request_key != NULL);
+
+ context = g_hash_table_lookup (self->pending_requests, request_key);
+
+ if (pincode != -1) {
+ dbus_g_method_return (context, pincode);
+ } else {
+ GError *error;
+ error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
+ "Pairing request rejected");
+ dbus_g_method_return_error (context, error);
+ }
+
+ g_hash_table_remove (self->pending_requests, request_key);
+ g_free (request_key);
+}
+
+/**
+ * bluetooth_applet_agent_reply_confirm:
+ *
+ * @self: a #BluetoothApplet
+ * @request_key: (transfer full): an opaque token given in the pincode-request signal
+ * @confirm: TRUE if operation was confirmed, FALSE otherwise
+ */
+void
+bluetooth_applet_agent_reply_confirm(BluetoothApplet* self, gchar* request_key, gboolean confirm)
+{
+ DBusGMethodInvocation* context;
+
+ g_return_if_fail (BLUETOOTH_IS_APPLET (self));
+ g_return_if_fail (request_key != NULL);
+
+ context = g_hash_table_lookup (self->pending_requests, request_key);
+
+ if (confirm) {
+ dbus_g_method_return (context);
+ } else {
+ GError *error;
+ error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
+ "Confirmation request rejected");
+ dbus_g_method_return_error (context, error);
+ }
+
+ g_hash_table_remove (self->pending_requests, request_key);
+ g_free (request_key);
+}
+
+/**
+ * bluetooth_applet_agent_reply_auth:
+ *
+ * @self: a #BluetoothApplet
+ * @request_key: (transfer full): an opaque token given in the pincode-request signal
+ * @auth: TRUE if operation was authorized, FALSE otherwise
+ * @trusted: TRUE if the operation should be authorized automatically in the future
+ */
+void
+bluetooth_applet_agent_reply_auth(BluetoothApplet* self, gchar* request_key, gboolean auth, gboolean trusted)
+{
+ DBusGMethodInvocation* context;
+
+ g_return_if_fail (BLUETOOTH_IS_APPLET (self));
+ g_return_if_fail (request_key != NULL);
+
+ context = g_hash_table_lookup (self->pending_requests, request_key);
+
+ if (auth) {
+ if (trusted)
+ bluetooth_client_set_trusted (self->client, request_key, TRUE);
+
+ dbus_g_method_return (context);
+ } else {
+ GError *error;
+ error = g_error_new(AGENT_ERROR, AGENT_ERROR_REJECT,
+ "Confirmation request rejected");
+ dbus_g_method_return_error (context, error);
+ }
+
+ g_hash_table_remove (self->pending_requests, request_key);
+ g_free (request_key);
+}
+
+#ifndef DBUS_TYPE_G_DICTIONARY
+#define DBUS_TYPE_G_DICTIONARY \
+ (dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
+#endif
+
+static char *
+device_get_name(DBusGProxy *proxy, char **long_name)
+{
+ GHashTable *hash;
+ GValue *value;
+ char *alias, *address;
+
+ g_return_val_if_fail (long_name != NULL, 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");
+ if (value == NULL) {
+ g_hash_table_destroy (hash);
+ return NULL;
+ }
+ address = g_value_dup_string(value);
+
+ value = g_hash_table_lookup(hash, "Name");
+ alias = value ? g_value_dup_string(value) : address;
+
+ g_hash_table_destroy (hash);
+
+ if (value)
+ *long_name = g_strdup_printf ("'%s' (%s)", alias, address);
+ else
+ *long_name = g_strdup_printf ("'%s'", address);
+
+ if (alias != address)
+ g_free (address);
+ return alias;
+}
+
+static gboolean pincode_request(DBusGMethodInvocation *context,
+ DBusGProxy *device, gpointer user_data)
+{
+ BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
+ char *name;
+ char *long_name = NULL;
+ const char *path;
+
+ name = device_get_name (device, &long_name);
+ path = dbus_g_proxy_get_path (device);
+ g_hash_table_insert (self->pending_requests, g_strdup (path), g_object_ref (context));
+
+ g_signal_emit (self, signals[SIGNAL_PINCODE_REQUEST], 0, path, name, long_name, TRUE);
+
+ g_free (name);
+ g_free (long_name);
+
+ return TRUE;
+}
+
+static gboolean passkey_request(DBusGMethodInvocation *context,
+ DBusGProxy *device, gpointer user_data)
+{
+ BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
+ char *name;
+ char *long_name = NULL;
+ const char *path;
+
+ name = device_get_name (device, &long_name);
+ path = dbus_g_proxy_get_path (device);
+ g_hash_table_insert (self->pending_requests, g_strdup (path), g_object_ref (context));
+
+ g_signal_emit (self, signals[SIGNAL_PINCODE_REQUEST], 0, path, name, long_name, FALSE);
+
+ g_free (name);
+ g_free (long_name);
+
+ return TRUE;
+}
+
+static gboolean
+confirm_request (DBusGMethodInvocation *context,
+ DBusGProxy *device,
+ guint pin,
+ gpointer user_data)
+{
+ BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
+ char *name;
+ char *long_name = NULL;
+ const char *path;
+
+ name = device_get_name (device, &long_name);
+ path = dbus_g_proxy_get_path (device);
+ g_hash_table_insert (self->pending_requests, g_strdup (path), g_object_ref (context));
+
+ g_signal_emit (self, signals[SIGNAL_CONFIRM_REQUEST], 0, path, name, long_name, pin);
+
+ g_free (name);
+ g_free (long_name);
+
+ return TRUE;
+}
+
+static gboolean
+authorize_request (DBusGMethodInvocation *context,
+ DBusGProxy *device,
+ const char *uuid,
+ gpointer user_data)
+{
+ BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
+ char *name;
+ char *long_name = NULL;
+ const char *path;
+
+ name = device_get_name (device, &long_name);
+ path = dbus_g_proxy_get_path (device);
+ g_hash_table_insert (self->pending_requests, g_strdup (path), g_object_ref (context));
+
+ g_signal_emit (self, signals[SIGNAL_AUTHORIZE_REQUEST], 0, path, name, long_name, uuid);
+
+ g_free (name);
+ g_free (long_name);
+
+ return TRUE;
+}
+
+static void
+cancel_request_single (gpointer key, gpointer value, gpointer user_data)
+{
+ DBusGMethodInvocation* request_context = value;
+ GError* result;
+
+ result = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT, "Agent callback cancelled");
+
+ dbus_g_method_return_error (request_context, result);
+}
+
+static gboolean
+cancel_request(DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
+
+ g_hash_table_foreach (self->pending_requests, cancel_request_single, NULL);
+ g_hash_table_remove_all (self->pending_requests);
+
+ g_signal_emit (self, signals[SIGNAL_CANCEL_REQUEST], 0);
+
+ return TRUE;
+}
+
+
+static void
+find_default_adapter (BluetoothApplet* self)
+{
+ GtkTreeIter iter;
+ gboolean cont;
+
+ if (self->default_adapter) {
+ gtk_tree_iter_free (self->default_adapter);
+ self->default_adapter = NULL;
+ }
+ if (self->agent) {
+ bluetooth_agent_unregister (self->agent);
+ g_object_unref (self->agent);
+ self->agent = NULL;
+ }
+ self->num_adapters_present = self->num_adapters_powered = 0;
+
+ cont = gtk_tree_model_get_iter_first (self->client_model, &iter);
+ while (cont) {
+ gboolean is_default, powered;
+
+ self->num_adapters_present++;
+
+ gtk_tree_model_get (self->client_model, &iter,
+ BLUETOOTH_COLUMN_DEFAULT, &is_default,
+ BLUETOOTH_COLUMN_POWERED, &powered,
+ -1);
+ if (powered)
+ self->num_adapters_powered++;
+ if (is_default && powered)
+ self->default_adapter = gtk_tree_iter_copy (&iter);
+
+ cont = gtk_tree_model_iter_next (self->client_model, &iter);
+ }
+
+ if (self->default_adapter) {
+ DBusGProxy* adapter;
+
+ gtk_tree_model_get (self->client_model, self->default_adapter,
+ BLUETOOTH_COLUMN_PROXY, &adapter, -1);
+
+ self->agent = bluetooth_agent_new();
+
+ bluetooth_agent_set_pincode_func (self->agent, pincode_request, self);
+ bluetooth_agent_set_passkey_func (self->agent, passkey_request, self);
+ bluetooth_agent_set_confirm_func (self->agent, confirm_request, self);
+ bluetooth_agent_set_authorize_func (self->agent, authorize_request, self);
+ bluetooth_agent_set_cancel_func (self->agent, cancel_request, self);
+
+ bluetooth_agent_register (self->agent, adapter);
+
+ g_object_unref (adapter);
+ }
+}
+
+static void
+device_added_or_changed (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ BluetoothApplet* self = BLUETOOTH_APPLET (data);
+
+ gboolean prev_visibility = bluetooth_applet_get_discoverable (self);
+ gint prev_num_adapters_powered = self->num_adapters_powered;
+ gint prev_num_adapters_present = self->num_adapters_present;
+
+ find_default_adapter (self);
+
+ if (bluetooth_applet_get_discoverable (self) != prev_visibility)
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DISCOVERABLE]);
+ if (prev_num_adapters_powered != self->num_adapters_powered ||
+ prev_num_adapters_present != self->num_adapters_present) {
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KILLSWITCH_STATE]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FULL_MENU]);
+ }
+
+ g_signal_emit (self, signals[SIGNAL_DEVICES_CHANGED], 0);
+}
+
+static void
+device_removed(GtkTreeModel *model,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ device_added_or_changed (model, path, NULL, user_data);
+}
+
+static gboolean
+set_powered_foreach (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ DBusGProxy *proxy = NULL;
+ GValue value = { 0, };
+
+ 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_unref (proxy);
+
+ return FALSE;
+}
+
+static void
+set_adapter_powered (BluetoothApplet* self)
+{
+ GtkTreeModel *adapters;
+
+ adapters = bluetooth_client_get_adapter_model (self->client);
+ gtk_tree_model_foreach (adapters, set_powered_foreach, NULL);
+ g_object_unref (adapters);
+}
+
+static gboolean
+device_has_uuid (const char **uuids, const char *uuid)
+{
+ guint i;
+
+ if (uuids == NULL)
+ return FALSE;
+
+ for (i = 0; uuids[i] != NULL; i++) {
+ if (g_str_equal (uuid, uuids[i]) != FALSE)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+killswitch_state_change (BluetoothKillswitch *kill_switch, KillswitchState state, gpointer user_data)
+{
+ BluetoothApplet *self = BLUETOOTH_APPLET (user_data);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KILLSWITCH_STATE]);
+}
+
+typedef struct {
+ BluetoothApplet* self;
+ BluetoothAppletConnectFunc func;
+ gpointer user_data;
+} ConnectionClosure;
+
+static void
+connection_callback (BluetoothClient* client, gboolean success, gpointer data)
+{
+ ConnectionClosure *closure = (ConnectionClosure*) data;
+
+ (*(closure->func)) (closure->self, success, closure->user_data);
+
+ g_free (closure);
+}
+
+/**
+ * bluetooth_applet_connect_device:
+ *
+ * @applet: a #BluetoothApplet
+ * @device: the device to connect
+ * @func: (scope async): a completion callback
+ * @data: user data
+ */
+gboolean
+bluetooth_applet_connect_device (BluetoothApplet* applet,
+ const char* device,
+ BluetoothAppletConnectFunc func,
+ gpointer data)
+{
+ ConnectionClosure *closure;
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (applet), FALSE);
+ g_return_val_if_fail (device != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ closure = g_new (ConnectionClosure, 1);
+ closure->self = applet;
+ closure->func = func;
+ closure->user_data = data;
+
+ return bluetooth_client_connect_service (applet->client, device, connection_callback, closure);
+}
+
+/**
+ * bluetooth_applet_disconnect_device:
+ *
+ * @applet: a #BluetoothApplet
+ * @device: the device to disconnect
+ * @func: (scope async): a completion callback
+ * @data: user data
+ */
+gboolean
+bluetooth_applet_disconnect_device (BluetoothApplet* applet,
+ const char* device,
+ BluetoothAppletConnectFunc func,
+ gpointer data)
+{
+ ConnectionClosure *closure;
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (applet), FALSE);
+ g_return_val_if_fail (device != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ closure = g_new (ConnectionClosure, 1);
+ closure->self = applet;
+ closure->func = func;
+ closure->user_data = data;
+
+ return bluetooth_client_disconnect_service (applet->client, device, connection_callback, closure);
+}
+
+/**
+ * bluetooth_applet_get_discoverable:
+ *
+ * @self: a #BluetoothApplet
+ *
+ * Returns: TRUE if the default adapter is discoverable, false otherwise
+ */
+gboolean
+bluetooth_applet_get_discoverable (BluetoothApplet* self)
+{
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), FALSE);
+
+ if (self->default_adapter == NULL)
+ return FALSE;
+
+ gtk_tree_model_get (self->client_model, self->default_adapter,
+ BLUETOOTH_COLUMN_DISCOVERABLE, &res,
+ -1);
+
+ return res;
+}
+
+/**
+ * bluetooth_applet_set_discoverable:
+ *
+ * @self: a #BluetoothApplet
+ * @disc:
+ */
+void
+bluetooth_applet_set_discoverable (BluetoothApplet* self, gboolean disc)
+{
+ g_return_if_fail (BLUETOOTH_IS_APPLET (self));
+
+ bluetooth_client_set_discoverable (self->client, disc, 0);
+}
+
+/**
+ * bluetooth_applet_get_killswitch_state:
+ *
+ * @self: a #BluetoothApplet
+ *
+ * Returns: the state of the killswitch, if one is present, or BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER otherwise
+ */
+BluetoothKillswitchState
+bluetooth_applet_get_killswitch_state (BluetoothApplet* self)
+{
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER);
+
+ if (bluetooth_killswitch_has_killswitches (self->killswitch_manager))
+ return bluetooth_killswitch_get_state (self->killswitch_manager);
+ else
+ return BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER;
+}
+
+/**
+ * bluetooth_applet_set_killswitch_state:
+ *
+ * @self: a #BluetoothApplet
+ * @state: the new state
+ *
+ * Returns: TRUE if the operation could be performed, FALSE otherwise
+ */
+gboolean
+bluetooth_applet_set_killswitch_state (BluetoothApplet* self, BluetoothKillswitchState state)
+{
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), FALSE);
+
+ if (bluetooth_killswitch_has_killswitches (self->killswitch_manager)) {
+ bluetooth_killswitch_set_state (self->killswitch_manager, state);
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+/**
+ * bluetooth_applet_get_show_full_menu:
+ *
+ * @self: a #BluetoothApplet
+ *
+ * Returns: TRUE if the full menu is to be shown, FALSE otherwise
+ * (full menu includes device submenus and global actions)
+ */
+gboolean
+bluetooth_applet_get_show_full_menu (BluetoothApplet* self)
+{
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), FALSE);
+
+ if (self->num_adapters_present == 0)
+ return FALSE;
+ else
+ /* the original code had <=, but does it make sense to have less
+ * adapters at all than adapters powered? */
+ return (self->num_adapters_present == self->num_adapters_powered) &&
+ (bluetooth_applet_get_killswitch_state(self) == BLUETOOTH_KILLSWITCH_STATE_UNBLOCKED);
+}
+
+/**
+ * bluetooth_applet_get_devices:
+ *
+ * @self: a #BluetoothApplet
+ *
+ * Returns: (element-type GnomeBluetoothApplet.SimpleDevice) (transfer full): Returns the devices which should be shown to the user
+ */
+GList*
+bluetooth_applet_get_devices (BluetoothApplet* self)
+{
+ GList* result = NULL;
+ GtkTreeIter iter;
+ gboolean cont;
+
+ g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), NULL);
+
+ if(self->default_adapter == NULL) // no adapter
+ return NULL;
+
+ cont = gtk_tree_model_iter_children (self->client_model, &iter, self->default_adapter);
+ while (cont) {
+ BluetoothSimpleDevice* dev = g_new (BluetoothSimpleDevice, 1);
+ GHashTable *services;
+ DBusGProxy *proxy;
+ char **uuids;
+
+ gtk_tree_model_get (self->client_model, &iter,
+ BLUETOOTH_COLUMN_ADDRESS, &dev->bdaddr,
+ BLUETOOTH_COLUMN_PROXY, &proxy,
+ BLUETOOTH_COLUMN_SERVICES, &services,
+ BLUETOOTH_COLUMN_ALIAS, &dev->alias,
+ BLUETOOTH_COLUMN_UUIDS, &uuids,
+ BLUETOOTH_COLUMN_TYPE, &dev->type,
+ -1);
+
+ dev->device_path = g_strdup (dbus_g_proxy_get_path (proxy));
+ g_object_unref (proxy);
+
+ /* If one service is connected, then we're connected */
+ dev->connected = FALSE;
+ dev->can_connect = FALSE;
+ if (services != NULL) {
+ dev->can_connect = TRUE;
+ GList *list, *l;
+ list = g_hash_table_get_values (services);
+ for (l = list; l != NULL; l = l->next) {
+ BluetoothStatus val = GPOINTER_TO_INT (l->data);
+ if (val == BLUETOOTH_STATUS_CONNECTED ||
+ val == BLUETOOTH_STATUS_PLAYING) {
+ dev->connected = TRUE;
+ break;
+ }
+ }
+ g_list_free (list);
+ }
+
+ dev->capabilities = 0;
+ dev->capabilities |= device_has_uuid ((const char **) uuids, "OBEXObjectPush") ? BLUETOOTH_CAPABILITIES_OBEX_PUSH : 0;
+ dev->capabilities |= device_has_uuid ((const char **) uuids, "OBEXFileTransfer") ? BLUETOOTH_CAPABILITIES_OBEX_FILE_TRANSFER : 0;
+
+ result = g_list_prepend (result, dev);
+ if (services != NULL)
+ g_hash_table_unref (services);
+ g_strfreev (uuids);
+
+ cont = gtk_tree_model_iter_next(self->client_model, &iter);
+ }
+ result = g_list_reverse (result);
+
+ return result;
+}
+
+static void
+bluetooth_applet_get_property (GObject* self, guint property_id, GValue* value, GParamSpec* pspec)
+{
+ switch (property_id) {
+ case PROP_FULL_MENU:
+ g_value_set_boolean (value, bluetooth_applet_get_show_full_menu (BLUETOOTH_APPLET (self)));
+ return;
+ case PROP_KILLSWITCH_STATE:
+ g_value_set_int (value, bluetooth_applet_get_killswitch_state (BLUETOOTH_APPLET (self)));
+ return;
+ case PROP_DISCOVERABLE:
+ g_value_set_boolean (value, bluetooth_applet_get_discoverable (BLUETOOTH_APPLET (self)));
+ return;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
+ }
+}
+
+static void
+bluetooth_applet_set_property (GObject* gobj, guint property_id, const GValue* value, GParamSpec* pspec)
+{
+ BluetoothApplet *self = BLUETOOTH_APPLET (gobj);
+
+ switch (property_id) {
+ case PROP_KILLSWITCH_STATE:
+ bluetooth_applet_set_killswitch_state (self, g_value_get_int (value));
+ return;
+ case PROP_DISCOVERABLE:
+ bluetooth_applet_set_discoverable (self, g_value_get_boolean (value));
+ return;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
+ }
+}
+
+static void
+bluetooth_applet_init (BluetoothApplet *self)
+{
+ GObject* gobject_client_model = NULL;
+
+ self->client = bluetooth_client_new ();
+ self->client_model = bluetooth_client_get_model (self->client);
+
+ self->default_adapter = NULL;
+ self->agent = bluetooth_agent_new ();
+
+ self->killswitch_manager = bluetooth_killswitch_new();
+ g_signal_connect (self->killswitch_manager, "state-changed", G_CALLBACK(killswitch_state_change), self);
+
+ self->pending_requests = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ dbus_g_error_domain_register(AGENT_ERROR, "org.bluez.Error", AGENT_ERROR_TYPE);
+
+ /* Make sure all the unblocked adapters are powered,
+ * so as to avoid seeing unpowered, but unblocked
+ * devices */
+ set_adapter_powered (self);
+ find_default_adapter (self);
+
+ gobject_client_model = G_OBJECT (self->client_model);
+ g_signal_connect(gobject_client_model, "row-inserted",
+ G_CALLBACK(device_added_or_changed), self);
+ g_signal_connect(gobject_client_model, "row-deleted",
+ G_CALLBACK(device_removed), self);
+ g_signal_connect (gobject_client_model, "row-changed",
+ G_CALLBACK (device_added_or_changed), self);
+}
+
+static void
+bluetooth_applet_dispose (GObject* self)
+{
+
+ BluetoothApplet* applet = BLUETOOTH_APPLET (self);
+
+ if (applet->client) {
+ g_object_unref (applet->client);
+ applet->client = NULL;
+ }
+
+ if (applet->killswitch_manager) {
+ g_object_unref (applet->killswitch_manager);
+ applet->killswitch_manager = NULL;
+ }
+
+ if (applet->client_model) {
+ g_object_unref (applet->client_model);
+ applet->client_model = NULL;
+ }
+
+ if (applet->agent) {
+ bluetooth_agent_unregister (applet->agent);
+ g_object_unref (applet->agent);
+ applet->agent = NULL;
+ }
+}
+
+static void
+bluetooth_applet_class_init (BluetoothAppletClass *klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = bluetooth_applet_dispose;
+ gobject_class->get_property = bluetooth_applet_get_property;
+ gobject_class->set_property = bluetooth_applet_set_property;
+
+ /* should be enum, but KillswitchState is not registered */
+ properties[PROP_KILLSWITCH_STATE] = g_param_spec_int ("killswitch-state",
+ "Killswitch state",
+ "State of Bluetooth hardware switches",
+ KILLSWITCH_STATE_NO_ADAPTER, KILLSWITCH_STATE_HARD_BLOCKED, KILLSWITCH_STATE_NO_ADAPTER, G_PARAM_READABLE | G_PARAM_WRITABLE);
+ g_object_class_install_property (gobject_class, PROP_KILLSWITCH_STATE, properties[PROP_KILLSWITCH_STATE]);
+
+ properties[PROP_DISCOVERABLE] = g_param_spec_boolean ("discoverable",
+ "Adapter visibility",
+ "Wheter the adapter is visible or not",
+ FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE);
+ g_object_class_install_property (gobject_class, PROP_DISCOVERABLE, properties[PROP_DISCOVERABLE]);
+
+ properties[PROP_FULL_MENU] = g_param_spec_boolean ("show-full-menu",
+ "Show the full applet menu",
+ "Show actions related to the adapter and other miscellanous in the main menu",
+ TRUE, G_PARAM_READABLE);
+ g_object_class_install_property (gobject_class, PROP_FULL_MENU, properties[PROP_FULL_MENU]);
+
+ signals[SIGNAL_DEVICES_CHANGED] = g_signal_new ("devices-changed", G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[SIGNAL_PINCODE_REQUEST] = g_signal_new ("pincode-request", G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL, marshal_VOID__STRING_STRING_STRING_BOOLEAN,
+ G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+
+ signals[SIGNAL_CONFIRM_REQUEST] = g_signal_new ("confirm-request", G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL, marshal_VOID__STRING_STRING_STRING_UINT,
+ G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
+
+ signals[SIGNAL_AUTHORIZE_REQUEST] = g_signal_new ("auth-request", G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL, marshal_VOID__STRING_STRING_STRING_STRING,
+ G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ signals[SIGNAL_CANCEL_REQUEST] = g_signal_new ("cancel-request", G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
diff --git a/applet/lib/bluetooth-applet.h b/applet/lib/bluetooth-applet.h
new file mode 100644
index 0000000..8ed14b1
--- /dev/null
+++ b/applet/lib/bluetooth-applet.h
@@ -0,0 +1,126 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ *
+ * 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
+ *
+ */
+
+/* inclusion guard */
+#ifndef __BLUETOOTH_APPLET_H__
+#define __BLUETOOTH_APPLET_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <lib/bluetooth-enums.h>
+
+/**
+ * BluetoothCapabilities:
+ *
+ * special actions that can be invoked on the object
+ */
+
+typedef enum {
+ BLUETOOTH_CAPABILITIES_NONE = 0,
+ BLUETOOTH_CAPABILITIES_OBEX_PUSH = 0x1,
+ BLUETOOTH_CAPABILITIES_OBEX_FILE_TRANSFER = 0x2
+} BluetoothCapabilities;
+
+/**
+ * BluetoothSimpleDevice:
+ *
+ * represents user visible properties of a device known to the default adapter
+ */
+
+typedef struct {
+ char* bdaddr;
+ char* device_path;
+ char* alias;
+ gboolean connected;
+ gboolean can_connect;
+ guint capabilities;
+ BluetoothType type;
+} BluetoothSimpleDevice;
+
+#define BLUETOOTH_TYPE_SIMPLE_DEVICE (bluetooth_simple_device_get_type ())
+
+GType bluetooth_simple_device_get_type (void) G_GNUC_CONST;
+
+/**
+ * BluetoothKillswitchState:
+ *
+ * public version of that found in bluetooth-killswitch.h
+ */
+
+typedef enum {
+ BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER = -1,
+ BLUETOOTH_KILLSWITCH_STATE_SOFT_BLOCKED = 0,
+ BLUETOOTH_KILLSWITCH_STATE_UNBLOCKED,
+ BLUETOOTH_KILLSWITCH_STATE_HARD_BLOCKED
+} BluetoothKillswitchState;
+
+/*
+ * Type macros.
+ */
+#define BLUETOOTH_TYPE_APPLET (bluetooth_applet_get_type ())
+#define BLUETOOTH_APPLET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BLUETOOTH_TYPE_APPLET, BluetoothApplet))
+#define BLUETOOTH_IS_APPLET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BLUETOOTH_TYPE_APPLET))
+#define BLUETOOTH_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BLUETOOTH_TYPE_APPLET, BluetoothAppletClass))
+#define BLUETOOTH_IS_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BLUETOOTH_TYPE_APPLET))
+#define BLUETOOTH_APPLET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BLUETOOTH_TYPE_APPLET, BluetoothAppletClass))
+
+/* These structs are fully opaque, type is not derivable */
+typedef struct _BluetoothApplet BluetoothApplet;
+typedef struct _BluetoothAppletClass BluetoothAppletClass;
+
+/* used by BLUETOOTH_TYPE_APPLET */
+GType bluetooth_applet_get_type (void) G_GNUC_CONST;
+
+/*
+ * Method definitions.
+ */
+
+GList* bluetooth_applet_get_devices(BluetoothApplet* self);
+
+BluetoothKillswitchState bluetooth_applet_get_killswitch_state(BluetoothApplet* self);
+gboolean bluetooth_applet_set_killswitch_state(BluetoothApplet* self, BluetoothKillswitchState state);
+
+gboolean bluetooth_applet_get_discoverable(BluetoothApplet* self);
+void bluetooth_applet_set_discoverable(BluetoothApplet* self, gboolean visible);
+
+typedef void (*BluetoothAppletConnectFunc) (BluetoothApplet *applet,
+ gboolean success,
+ gpointer data);
+
+gboolean bluetooth_applet_connect_device(BluetoothApplet *applet,
+ const char *device,
+ BluetoothAppletConnectFunc func,
+ gpointer data);
+gboolean bluetooth_applet_disconnect_device (BluetoothApplet *applet,
+ const char *device,
+ BluetoothAppletConnectFunc func,
+ gpointer data);
+
+gboolean bluetooth_applet_get_show_full_menu(BluetoothApplet* self);
+
+void bluetooth_applet_agent_reply_passkey(BluetoothApplet* self, gchar* request_key, gchar* passkey);
+void bluetooth_applet_agent_reply_pincode(BluetoothApplet* self, gchar* request_key, gint pincode);
+void bluetooth_applet_agent_reply_confirm(BluetoothApplet* self, gchar* request_key, gboolean confirm);
+void bluetooth_applet_agent_reply_auth(BluetoothApplet* self, gchar* request_key, gboolean auth, gboolean trusted);
+
+#endif /* __BLUETOOTH_APPLET_H__ */
diff --git a/applet/lib/marshal.list b/applet/lib/marshal.list
new file mode 100644
index 0000000..ba5a1f8
--- /dev/null
+++ b/applet/lib/marshal.list
@@ -0,0 +1,3 @@
+VOID:STRING,STRING,STRING,BOOLEAN
+VOID:STRING,STRING,STRING,UINT
+VOID:STRING,STRING,STRING,STRING
diff --git a/configure.ac b/configure.ac
index 505f819..ea5bcfa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -209,6 +209,7 @@ AC_OUTPUT(Makefile
icons/Makefile
lib/Makefile
lib/plugins/Makefile
+ applet/lib/Makefile
applet/Makefile
applet/bluetooth-applet.desktop.in
properties/Makefile
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]