1
/* -*- tab-width: 8 -*-
3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2010 Giovanni Campagna <scampa.giovanni@gmail.com>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
#include <glib/gi18n.h>
26
#include <dbus/dbus-glib.h>
29
#include <bluetooth-applet.h>
30
#include <bluetooth-client.h>
31
#include <bluetooth-client-private.h>
32
#include <bluetooth-killswitch.h>
33
#include <bluetooth-agent.h>
38
bluetooth_simple_device_copy (gpointer boxed)
40
BluetoothSimpleDevice* origin = (BluetoothSimpleDevice*) boxed;
42
BluetoothSimpleDevice* result = g_new (BluetoothSimpleDevice, 1);
43
result->bdaddr = g_strdup (origin->bdaddr);
44
result->device_path = g_strdup (origin->device_path);
45
result->alias = g_strdup (origin->alias);
46
result->connected = origin->connected;
47
result->can_connect = origin->can_connect;
48
result->capabilities = origin->capabilities;
49
result->type = origin->type;
51
return (gpointer)result;
55
bluetooth_simple_device_free (gpointer boxed)
57
BluetoothSimpleDevice* obj = (BluetoothSimpleDevice*) boxed;
59
g_free (obj->device_path);
65
G_DEFINE_BOXED_TYPE(BluetoothSimpleDevice, bluetooth_simple_device, bluetooth_simple_device_copy, bluetooth_simple_device_free)
67
struct _BluetoothApplet
69
GObject parent_instance;
71
BluetoothKillswitch* killswitch_manager;
72
BluetoothClient* client;
73
GtkTreeModel* device_model;
74
gulong signal_row_added;
75
gulong signal_row_changed;
76
gulong signal_row_deleted;
77
DBusGProxy* default_adapter;
78
BluetoothAgent* agent;
79
GHashTable* pending_requests;
81
gint num_adapters_powered;
82
gint num_adapters_present;
85
struct _BluetoothAppletClass {
86
GObjectClass parent_class;
89
G_DEFINE_TYPE(BluetoothApplet, bluetooth_applet, G_TYPE_OBJECT)
93
PROP_KILLSWITCH_STATE,
98
static GParamSpec *properties[PROP_LAST];
101
SIGNAL_DEVICES_CHANGED,
103
SIGNAL_PINCODE_REQUEST,
104
SIGNAL_CONFIRM_REQUEST,
105
SIGNAL_AUTHORIZE_REQUEST,
106
SIGNAL_CANCEL_REQUEST,
111
guint signals[SIGNAL_LAST];
114
GSimpleAsyncResult *result;
119
mount_ready_cb (GObject *object,
120
GAsyncResult *result,
123
GError *error = NULL;
124
GFile *file = G_FILE (object);
125
char *uri = g_file_get_uri (file);
126
MountClosure *closure = user_data;
128
if (g_file_mount_enclosing_volume_finish (file, result, &error) == FALSE) {
129
/* Ignore "already mounted" error */
130
if (error->domain == G_IO_ERROR &&
131
error->code == G_IO_ERROR_ALREADY_MOUNTED) {
132
g_error_free (error);
138
gtk_show_uri (NULL, uri, closure->timestamp, &error);
142
g_simple_async_result_set_from_error (closure->result, error);
143
g_error_free (error);
145
g_simple_async_result_set_op_res_gboolean (closure->result, TRUE);
148
g_simple_async_result_complete (closure->result);
151
g_object_unref (closure->result);
156
* bluetooth_applet_browse_address_finish:
158
* @applet: a #BluetoothApplet
159
* @result: the #GAsyncResult from the callback
162
* Returns: TRUE if the operation was successful, FALSE if error is set
165
bluetooth_applet_browse_address_finish (BluetoothApplet *applet,
166
GAsyncResult *result,
169
GSimpleAsyncResult *simple;
171
g_return_val_if_fail (BLUETOOTH_IS_APPLET (applet), FALSE);
172
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (applet), bluetooth_applet_browse_address), FALSE);
174
simple = G_SIMPLE_ASYNC_RESULT (result);
175
if (g_simple_async_result_propagate_error (simple, error))
182
* bluetooth_applet_browse_address:
184
* Opens a Bluetooth device in Nautilus
185
* @applet: a #BluetoothApplet
186
* @address: the bluetooth device to browse
187
* @callback: (scope async): the completion callback
190
void bluetooth_applet_browse_address (BluetoothApplet *applet,
193
GAsyncReadyCallback callback,
198
MountClosure *closure;
200
g_return_if_fail (BLUETOOTH_IS_APPLET (applet));
201
g_return_if_fail (address != NULL);
203
uri = g_strdup_printf ("obex://[%s]/", address);
204
file = g_file_new_for_uri (uri);
206
closure = g_new (MountClosure, 1);
207
closure->result = g_simple_async_result_new (G_OBJECT (applet), callback, user_data, bluetooth_applet_browse_address);
208
closure->timestamp = timestamp;
209
g_file_mount_enclosing_volume(file, G_MOUNT_MOUNT_NONE, NULL, NULL, mount_ready_cb, closure);
212
g_object_unref (file);
216
* bluetooth_applet_send_to_address:
218
* Send a file to a bluetooth device
219
* @applet: a #BluetoothApplet
220
* @address: the target
221
* @alias: the string to display for the device
223
void bluetooth_applet_send_to_address (BluetoothApplet *applet,
231
g_return_if_fail (BLUETOOTH_IS_APPLET (applet));
233
a = g_ptr_array_new ();
234
g_ptr_array_add (a, "bluetooth-sendto");
235
if (address != NULL) {
238
s = g_strdup_printf ("--device=\"%s\"", address);
239
g_ptr_array_add (a, s);
241
if (address != NULL && alias != NULL) {
244
s = g_strdup_printf ("--name=\"%s\"", alias);
245
g_ptr_array_add (a, s);
247
g_ptr_array_add (a, NULL);
249
if (g_spawn_async(NULL, (char **) a->pdata, NULL,
250
G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err) == FALSE) {
251
g_printerr("Couldn't execute command: %s\n", err->message);
255
for (i = 1; a->pdata[i] != NULL; i++)
256
g_free (a->pdata[i]);
258
g_ptr_array_free (a, TRUE);
262
* bluetooth_applet_agent_reply_pincode:
264
* @self: a #BluetoothApplet
265
* @request_key: an opaque token given in the pincode-request signal
266
* @pincode: (allow-none): the PIN code entered by the user, as a string, or NULL if the dialog was dismissed
269
bluetooth_applet_agent_reply_pincode (BluetoothApplet *self,
270
const char *request_key,
273
DBusGMethodInvocation* context;
275
g_return_if_fail (BLUETOOTH_IS_APPLET (self));
276
g_return_if_fail (request_key != NULL);
278
context = g_hash_table_lookup (self->pending_requests, request_key);
280
if (pincode != NULL) {
281
dbus_g_method_return (context, pincode);
284
error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
285
"Pairing request rejected");
286
dbus_g_method_return_error (context, error);
289
g_hash_table_remove (self->pending_requests, request_key);
293
* bluetooth_applet_agent_reply_passkey:
295
* @self: a #BluetoothApplet
296
* @request_key: an opaque token given in the pincode-request signal
297
* @passkey: the numeric PIN code entered by the user, or -1 if the dialog was dismissed
300
bluetooth_applet_agent_reply_passkey (BluetoothApplet *self,
301
const char *request_key,
304
DBusGMethodInvocation* context;
306
g_return_if_fail (BLUETOOTH_IS_APPLET (self));
307
g_return_if_fail (request_key != NULL);
309
context = g_hash_table_lookup (self->pending_requests, request_key);
312
dbus_g_method_return (context, passkey);
315
error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
316
"Pairing request rejected");
317
dbus_g_method_return_error (context, error);
320
g_hash_table_remove (self->pending_requests, request_key);
324
* bluetooth_applet_agent_reply_confirm:
326
* @self: a #BluetoothApplet
327
* @request_key: an opaque token given in the pincode-request signal
328
* @confirm: TRUE if operation was confirmed, FALSE otherwise
331
bluetooth_applet_agent_reply_confirm (BluetoothApplet *self,
332
const char *request_key,
335
DBusGMethodInvocation* context;
337
g_return_if_fail (BLUETOOTH_IS_APPLET (self));
338
g_return_if_fail (request_key != NULL);
340
context = g_hash_table_lookup (self->pending_requests, request_key);
343
dbus_g_method_return (context);
346
error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
347
"Confirmation request rejected");
348
dbus_g_method_return_error (context, error);
351
g_hash_table_remove (self->pending_requests, request_key);
355
* bluetooth_applet_agent_reply_auth:
357
* @self: a #BluetoothApplet
358
* @request_key: an opaque token given in the pincode-request signal
359
* @auth: TRUE if operation was authorized, FALSE otherwise
360
* @trusted: TRUE if the operation should be authorized automatically in the future
363
bluetooth_applet_agent_reply_auth (BluetoothApplet *self,
364
const char *request_key,
368
DBusGMethodInvocation* context;
370
g_return_if_fail (BLUETOOTH_IS_APPLET (self));
371
g_return_if_fail (request_key != NULL);
373
context = g_hash_table_lookup (self->pending_requests, request_key);
377
bluetooth_client_set_trusted (self->client, request_key, TRUE);
379
dbus_g_method_return (context);
382
error = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT,
383
"Confirmation request rejected");
384
dbus_g_method_return_error (context, error);
387
g_hash_table_remove (self->pending_requests, request_key);
390
#ifndef DBUS_TYPE_G_DICTIONARY
391
#define DBUS_TYPE_G_DICTIONARY \
392
(dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
396
device_get_name (DBusGProxy *proxy, char **long_name)
400
char *alias, *address;
402
g_return_val_if_fail (long_name != NULL, NULL);
404
if (dbus_g_proxy_call (proxy, "GetProperties", NULL,
406
DBUS_TYPE_G_DICTIONARY, &hash,
407
G_TYPE_INVALID) == FALSE) {
411
value = g_hash_table_lookup (hash, "Address");
413
g_hash_table_destroy (hash);
416
address = g_value_dup_string (value);
418
value = g_hash_table_lookup (hash, "Name");
419
alias = value ? g_value_dup_string (value) : address;
421
g_hash_table_destroy (hash);
424
*long_name = g_strdup_printf ("'%s' (%s)", alias, address);
426
*long_name = g_strdup_printf ("'%s'", address);
428
if (alias != address)
434
pincode_request (DBusGMethodInvocation *context,
438
BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
440
char *long_name = NULL;
443
name = device_get_name (device, &long_name);
444
path = dbus_g_proxy_get_path (device);
445
g_hash_table_insert (self->pending_requests, g_strdup (path), context);
447
g_signal_emit (self, signals[SIGNAL_PINCODE_REQUEST], 0, path, name, long_name, FALSE);
456
passkey_request (DBusGMethodInvocation *context,
460
BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
462
char *long_name = NULL;
465
name = device_get_name (device, &long_name);
466
path = dbus_g_proxy_get_path (device);
467
g_hash_table_insert (self->pending_requests, g_strdup (path), context);
469
g_signal_emit (self, signals[SIGNAL_PINCODE_REQUEST], 0, path, name, long_name, TRUE);
478
confirm_request (DBusGMethodInvocation *context,
483
BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
485
char *long_name = NULL;
488
name = device_get_name (device, &long_name);
489
path = dbus_g_proxy_get_path (device);
490
g_hash_table_insert (self->pending_requests, g_strdup (path), context);
492
g_signal_emit (self, signals[SIGNAL_CONFIRM_REQUEST], 0, path, name, long_name, pin);
501
authorize_request (DBusGMethodInvocation *context,
506
BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
508
char *long_name = NULL;
511
name = device_get_name (device, &long_name);
512
path = dbus_g_proxy_get_path (device);
513
g_hash_table_insert (self->pending_requests, g_strdup (path), context);
515
g_signal_emit (self, signals[SIGNAL_AUTHORIZE_REQUEST], 0, path, name, long_name, uuid);
524
cancel_request_single (gpointer key, gpointer value, gpointer user_data)
526
DBusGMethodInvocation* request_context = value;
530
result = g_error_new (AGENT_ERROR, AGENT_ERROR_REJECT, "Agent callback cancelled");
531
dbus_g_method_return_error (request_context, result);
536
cancel_request(DBusGMethodInvocation *context,
539
BluetoothApplet* self = BLUETOOTH_APPLET (user_data);
541
g_hash_table_foreach (self->pending_requests, cancel_request_single, NULL);
542
g_hash_table_remove_all (self->pending_requests);
544
g_signal_emit (self, signals[SIGNAL_CANCEL_REQUEST], 0);
550
device_added_or_changed (GtkTreeModel *model,
555
BluetoothApplet *self = BLUETOOTH_APPLET (data);
557
g_signal_emit (self, signals[SIGNAL_DEVICES_CHANGED], 0);
561
device_removed (GtkTreeModel *model,
565
device_added_or_changed (model, path, NULL, user_data);
569
default_adapter_changed (GObject *client,
573
BluetoothApplet* self = BLUETOOTH_APPLET (data);
575
if (self->default_adapter)
576
g_object_unref (self->default_adapter);
577
self->default_adapter = bluetooth_client_get_default_adapter (self->client);
579
if (self->device_model) {
580
g_signal_handler_disconnect (self->device_model, self->signal_row_added);
581
g_signal_handler_disconnect (self->device_model, self->signal_row_changed);
582
g_signal_handler_disconnect (self->device_model, self->signal_row_deleted);
583
g_object_unref (self->device_model);
585
if (self->default_adapter)
586
self->device_model = bluetooth_client_get_device_model (self->client, self->default_adapter);
588
self->device_model = NULL;
590
if (self->device_model) {
591
self->signal_row_added = g_signal_connect (self->device_model, "row-inserted",
592
G_CALLBACK(device_added_or_changed), self);
593
self->signal_row_deleted = g_signal_connect (self->device_model, "row-deleted",
594
G_CALLBACK(device_removed), self);
595
self->signal_row_changed = g_signal_connect (self->device_model, "row-changed",
596
G_CALLBACK (device_added_or_changed), self);
600
g_object_unref (self->agent);
602
if (self->default_adapter) {
603
self->agent = bluetooth_agent_new ();
604
g_object_add_weak_pointer (G_OBJECT (self->agent), (void**) &(self->agent));
606
bluetooth_agent_set_pincode_func (self->agent, pincode_request, self);
607
bluetooth_agent_set_passkey_func (self->agent, passkey_request, self);
608
bluetooth_agent_set_authorize_func (self->agent, authorize_request, self);
609
bluetooth_agent_set_confirm_func (self->agent, confirm_request, self);
610
bluetooth_agent_set_cancel_func (self->agent, cancel_request, self);
612
bluetooth_agent_register (self->agent, self->default_adapter);
615
g_signal_emit (self, signals[SIGNAL_DEVICES_CHANGED], 0);
619
default_adapter_powered_changed (GObject *client,
623
BluetoothApplet *self = BLUETOOTH_APPLET (data);
625
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FULL_MENU]);
629
default_adapter_discoverable_changed (GObject *client,
633
BluetoothApplet *self = BLUETOOTH_APPLET (data);
635
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DISCOVERABLE]);
639
set_powered_foreach (GtkTreeModel *model,
644
DBusGProxy *proxy = NULL;
645
GValue value = { 0, };
647
gtk_tree_model_get (model, iter,
648
BLUETOOTH_COLUMN_PROXY, &proxy, -1);
652
g_value_init (&value, G_TYPE_BOOLEAN);
653
g_value_set_boolean (&value, TRUE);
655
dbus_g_proxy_call_no_reply (proxy, "SetProperty",
656
G_TYPE_STRING, "Powered",
657
G_TYPE_VALUE, &value,
661
g_value_unset (&value);
662
g_object_unref (proxy);
668
set_adapter_powered (BluetoothApplet* self)
670
GtkTreeModel *adapters;
672
adapters = bluetooth_client_get_adapter_model (self->client);
673
gtk_tree_model_foreach (adapters, set_powered_foreach, NULL);
674
g_object_unref (adapters);
678
device_has_uuid (const char **uuids, const char *uuid)
685
for (i = 0; uuids[i] != NULL; i++) {
686
if (g_str_equal (uuid, uuids[i]) != FALSE)
693
killswitch_state_change (BluetoothKillswitch *kill_switch, KillswitchState state, gpointer user_data)
695
BluetoothApplet *self = BLUETOOTH_APPLET (user_data);
697
g_object_notify (G_OBJECT (self), "killswitch-state");
701
BluetoothApplet* self;
702
BluetoothAppletConnectFunc func;
707
connection_callback (BluetoothClient* client, gboolean success, gpointer data)
709
ConnectionClosure *closure = (ConnectionClosure*) data;
711
(*(closure->func)) (closure->self, success, closure->user_data);
717
* bluetooth_applet_connect_device:
719
* @applet: a #BluetoothApplet
720
* @device: the device to connect
721
* @func: (scope async): a completion callback
725
bluetooth_applet_connect_device (BluetoothApplet* applet,
727
BluetoothAppletConnectFunc func,
730
ConnectionClosure *closure;
732
g_return_val_if_fail (BLUETOOTH_IS_APPLET (applet), FALSE);
733
g_return_val_if_fail (device != NULL, FALSE);
734
g_return_val_if_fail (func != NULL, FALSE);
736
closure = g_new (ConnectionClosure, 1);
737
closure->self = applet;
738
closure->func = func;
739
closure->user_data = data;
741
return bluetooth_client_connect_service (applet->client, device, connection_callback, closure);
745
* bluetooth_applet_disconnect_device:
747
* @applet: a #BluetoothApplet
748
* @device: the device to disconnect
749
* @func: (scope async): a completion callback
753
bluetooth_applet_disconnect_device (BluetoothApplet* applet,
755
BluetoothAppletConnectFunc func,
758
ConnectionClosure *closure;
760
g_return_val_if_fail (BLUETOOTH_IS_APPLET (applet), FALSE);
761
g_return_val_if_fail (device != NULL, FALSE);
762
g_return_val_if_fail (func != NULL, FALSE);
764
closure = g_new (ConnectionClosure, 1);
765
closure->self = applet;
766
closure->func = func;
767
closure->user_data = data;
769
return bluetooth_client_disconnect_service (applet->client, device, connection_callback, closure);
773
* bluetooth_applet_get_discoverable:
775
* @self: a #BluetoothApplet
777
* Returns: TRUE if the default adapter is discoverable, false otherwise
780
bluetooth_applet_get_discoverable (BluetoothApplet* self)
782
g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), FALSE);
784
return bluetooth_client_get_discoverable (self->client);
788
* bluetooth_applet_set_discoverable:
790
* @self: a #BluetoothApplet
794
bluetooth_applet_set_discoverable (BluetoothApplet* self, gboolean disc)
796
g_return_if_fail (BLUETOOTH_IS_APPLET (self));
798
bluetooth_client_set_discoverable (self->client, disc, 0);
802
* bluetooth_applet_get_killswitch_state:
804
* @self: a #BluetoothApplet
806
* Returns: the state of the killswitch, if one is present, or BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER otherwise
808
BluetoothKillswitchState
809
bluetooth_applet_get_killswitch_state (BluetoothApplet* self)
812
g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER);
814
if (bluetooth_killswitch_has_killswitches (self->killswitch_manager))
815
return bluetooth_killswitch_get_state (self->killswitch_manager);
817
return BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER;
821
* bluetooth_applet_set_killswitch_state:
823
* @self: a #BluetoothApplet
824
* @state: the new state
826
* Returns: TRUE if the operation could be performed, FALSE otherwise
829
bluetooth_applet_set_killswitch_state (BluetoothApplet* self, BluetoothKillswitchState state)
832
g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), FALSE);
834
if (bluetooth_killswitch_has_killswitches (self->killswitch_manager)) {
835
bluetooth_killswitch_set_state (self->killswitch_manager, state);
842
* bluetooth_applet_get_show_full_menu:
844
* @self: a #BluetoothApplet
846
* Returns: TRUE if the full menu is to be shown, FALSE otherwise
847
* (full menu includes device submenus and global actions)
850
bluetooth_applet_get_show_full_menu (BluetoothApplet* self)
852
gboolean has_adapter, has_powered_adapter;
853
g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), FALSE);
855
has_adapter = self->default_adapter != NULL;
856
g_object_get (G_OBJECT (self->client), "default-adapter-powered", &has_powered_adapter, NULL);
861
return has_powered_adapter &&
862
bluetooth_applet_get_killswitch_state(self) == BLUETOOTH_KILLSWITCH_STATE_UNBLOCKED;
865
static BluetoothSimpleDevice *
866
bluetooth_applet_create_device_from_iter (GtkTreeModel *model,
868
gboolean check_proxy)
870
BluetoothSimpleDevice *dev;
871
GHashTable *services;
875
dev = g_new0 (BluetoothSimpleDevice, 1);
877
gtk_tree_model_get (model, iter,
878
BLUETOOTH_COLUMN_ADDRESS, &dev->bdaddr,
879
BLUETOOTH_COLUMN_PROXY, &proxy,
880
BLUETOOTH_COLUMN_SERVICES, &services,
881
BLUETOOTH_COLUMN_ALIAS, &dev->alias,
882
BLUETOOTH_COLUMN_UUIDS, &uuids,
883
BLUETOOTH_COLUMN_TYPE, &dev->type,
886
if (dev->bdaddr == NULL || dev->alias == NULL ||
887
(check_proxy != FALSE && proxy == NULL)) {
889
g_object_unref (proxy);
891
if (services != NULL)
892
g_hash_table_unref (services);
893
bluetooth_simple_device_free (dev);
899
dev->device_path = g_strdup (dbus_g_proxy_get_path (proxy));
900
g_object_unref (proxy);
903
/* If one service is connected, then we're connected */
904
dev->connected = FALSE;
905
dev->can_connect = FALSE;
906
if (services != NULL) {
909
dev->can_connect = TRUE;
910
list = g_hash_table_get_values (services);
911
for (l = list; l != NULL; l = l->next) {
912
BluetoothStatus val = GPOINTER_TO_INT (l->data);
913
if (val == BLUETOOTH_STATUS_CONNECTED ||
914
val == BLUETOOTH_STATUS_PLAYING) {
915
dev->connected = TRUE;
922
dev->capabilities = 0;
923
dev->capabilities |= device_has_uuid ((const char **) uuids, "OBEXObjectPush") ? BLUETOOTH_CAPABILITIES_OBEX_PUSH : 0;
924
dev->capabilities |= device_has_uuid ((const char **) uuids, "OBEXFileTransfer") ? BLUETOOTH_CAPABILITIES_OBEX_FILE_TRANSFER : 0;
926
if (services != NULL)
927
g_hash_table_unref (services);
934
* bluetooth_applet_get_devices:
936
* @self: a #BluetoothApplet
938
* Returns: (element-type GnomeBluetoothApplet.SimpleDevice) (transfer full): Returns the devices which should be shown to the user
941
bluetooth_applet_get_devices (BluetoothApplet* self)
943
GList* result = NULL;
947
g_return_val_if_fail (BLUETOOTH_IS_APPLET (self), NULL);
950
if (self->default_adapter == NULL)
953
cont = gtk_tree_model_get_iter_first (self->device_model, &iter);
955
BluetoothSimpleDevice *dev;
957
dev = bluetooth_applet_create_device_from_iter (self->device_model, &iter, TRUE);
960
result = g_list_prepend (result, dev);
962
cont = gtk_tree_model_iter_next (self->device_model, &iter);
965
result = g_list_reverse (result);
971
bluetooth_applet_get_property (GObject *self,
976
switch (property_id) {
978
g_value_set_boolean (value, bluetooth_applet_get_show_full_menu (BLUETOOTH_APPLET (self)));
980
case PROP_KILLSWITCH_STATE:
981
g_value_set_int (value, bluetooth_applet_get_killswitch_state (BLUETOOTH_APPLET (self)));
983
case PROP_DISCOVERABLE:
984
g_value_set_boolean (value, bluetooth_applet_get_discoverable (BLUETOOTH_APPLET (self)));
987
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
992
bluetooth_applet_set_property (GObject *gobj,
997
BluetoothApplet *self = BLUETOOTH_APPLET (gobj);
999
switch (property_id) {
1000
case PROP_KILLSWITCH_STATE:
1001
bluetooth_applet_set_killswitch_state (self, g_value_get_int (value));
1003
case PROP_DISCOVERABLE:
1004
bluetooth_applet_set_discoverable (self, g_value_get_boolean (value));
1007
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
1012
bluetooth_applet_init (BluetoothApplet *self)
1014
self->client = bluetooth_client_new ();
1015
self->device_model = NULL;
1017
self->default_adapter = NULL;
1020
self->killswitch_manager = bluetooth_killswitch_new ();
1021
g_signal_connect (self->killswitch_manager, "state-changed", G_CALLBACK(killswitch_state_change), self);
1023
self->pending_requests = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1024
dbus_g_error_domain_register (AGENT_ERROR, "org.bluez.Error", AGENT_ERROR_TYPE);
1026
/* Make sure all the unblocked adapters are powered,
1027
* so as to avoid seeing unpowered, but unblocked
1029
set_adapter_powered (self);
1030
default_adapter_changed (NULL, NULL, self);
1032
g_signal_connect (self->client, "notify::default-adapter", G_CALLBACK (default_adapter_changed), self);
1033
g_signal_connect (self->client, "notify::default-adapter-powered", G_CALLBACK (default_adapter_powered_changed), self);
1034
g_signal_connect (self->client, "notify::default-adapter-discoverable", G_CALLBACK (default_adapter_discoverable_changed), self);
1038
bluetooth_applet_dispose (GObject* self)
1041
BluetoothApplet* applet = BLUETOOTH_APPLET (self);
1043
if (applet->client) {
1044
g_object_unref (applet->client);
1045
applet->client = NULL;
1048
if (applet->killswitch_manager) {
1049
g_object_unref (applet->killswitch_manager);
1050
applet->killswitch_manager = NULL;
1053
if (applet->device_model) {
1054
g_object_unref (applet->device_model);
1055
applet->device_model = NULL;
1058
if (applet->agent) {
1059
g_object_unref (applet->agent);
1060
applet->agent = NULL;
1065
bluetooth_applet_class_init (BluetoothAppletClass *klass)
1067
GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
1069
gobject_class->dispose = bluetooth_applet_dispose;
1070
gobject_class->get_property = bluetooth_applet_get_property;
1071
gobject_class->set_property = bluetooth_applet_set_property;
1073
/* should be enum, but KillswitchState is not registered */
1074
properties[PROP_KILLSWITCH_STATE] = g_param_spec_int ("killswitch-state",
1076
"State of Bluetooth hardware switches",
1077
KILLSWITCH_STATE_NO_ADAPTER, KILLSWITCH_STATE_HARD_BLOCKED, KILLSWITCH_STATE_NO_ADAPTER,
1078
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1079
g_object_class_install_property (gobject_class, PROP_KILLSWITCH_STATE, properties[PROP_KILLSWITCH_STATE]);
1081
properties[PROP_DISCOVERABLE] = g_param_spec_boolean ("discoverable",
1082
"Adapter visibility",
1083
"Whether the adapter is visible or not",
1084
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1085
g_object_class_install_property (gobject_class, PROP_DISCOVERABLE, properties[PROP_DISCOVERABLE]);
1087
properties[PROP_FULL_MENU] = g_param_spec_boolean ("show-full-menu",
1088
"Show the full applet menu",
1089
"Show actions related to the adapter and other miscellanous in the main menu",
1090
TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1091
g_object_class_install_property (gobject_class, PROP_FULL_MENU, properties[PROP_FULL_MENU]);
1093
signals[SIGNAL_DEVICES_CHANGED] = g_signal_new ("devices-changed", G_TYPE_FROM_CLASS (gobject_class),
1094
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
1097
signals[SIGNAL_PINCODE_REQUEST] = g_signal_new ("pincode-request", G_TYPE_FROM_CLASS (gobject_class),
1098
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, marshal_VOID__STRING_STRING_STRING_BOOLEAN,
1099
G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
1101
signals[SIGNAL_CONFIRM_REQUEST] = g_signal_new ("confirm-request", G_TYPE_FROM_CLASS (gobject_class),
1102
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, marshal_VOID__STRING_STRING_STRING_UINT,
1103
G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
1105
signals[SIGNAL_AUTHORIZE_REQUEST] = g_signal_new ("auth-request", G_TYPE_FROM_CLASS (gobject_class),
1106
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, marshal_VOID__STRING_STRING_STRING_STRING,
1107
G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1109
signals[SIGNAL_CANCEL_REQUEST] = g_signal_new ("cancel-request", G_TYPE_FROM_CLASS (gobject_class),
1110
G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,