~timchen119/ubuntu/trusty/gnome-bluetooth/lp1035431

« back to all changes in this revision

Viewing changes to applet/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2011-02-27 15:45:22 UTC
  • mfrom: (1.3.2 upstream)
  • mto: (2.2.3 experimental) (1.5.1)
  • mto: This revision was merged to the branch mainline in revision 53.
  • Revision ID: james.westby@ubuntu.com-20110227154522-dnnoqasv5v3mv42a
Tags: upstream-2.91.5
ImportĀ upstreamĀ versionĀ 2.91.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <glib/gi18n.h>
30
30
#include <gtk/gtk.h>
31
31
 
32
 
#include <gconf/gconf-client.h>
33
 
#include <unique/uniqueapp.h>
34
 
 
 
32
#include <bluetooth-chooser.h>
35
33
#include <bluetooth-client.h>
36
 
#include <bluetooth-client-private.h>
37
 
#include <bluetooth-chooser.h>
38
 
#include <bluetooth-killswitch.h>
39
34
 
 
35
#include "bluetooth-applet.h"
40
36
#include "notify.h"
41
37
#include "agent.h"
42
38
 
43
39
static gboolean option_debug = FALSE;
44
 
static BluetoothClient *client;
45
 
static GtkTreeModel *devices_model;
46
 
static guint num_adapters_present = 0;
47
 
static guint num_adapters_powered = 0;
 
40
static BluetoothApplet *applet = NULL;
 
41
static GSettings *settings = NULL;
48
42
static gboolean show_icon_pref = TRUE;
49
 
 
50
 
#define PREF_DIR                "/apps/bluetooth-manager"
51
 
#define PREF_SHOW_ICON          PREF_DIR "/show_icon"
52
 
 
53
 
#define KEYBOARD_PREFS          "gnome-keyboard-properties"
54
 
#define MOUSE_PREFS             "gnome-mouse-properties"
 
43
static gboolean discover_lock = FALSE;
 
44
 
 
45
#define SCHEMA_NAME             "org.gnome.Bluetooth"
 
46
#define PREF_SHOW_ICON          "show-icon"
 
47
 
 
48
#define GNOMECC                 "gnome-control-center"
 
49
#define KEYBOARD_PREFS          GNOMECC " keyboard"
 
50
#define MOUSE_PREFS             GNOMECC " mouse"
 
51
#define SOUND_PREFS             GNOMECC " sound"
55
52
 
56
53
enum {
57
54
        CONNECTED,
60
57
        DISCONNECTING
61
58
};
62
59
 
63
 
static GConfClient* gconf;
64
 
static BluetoothKillswitch *killswitch = NULL;
65
 
 
66
60
static GtkBuilder *xml = NULL;
67
61
static GtkActionGroup *devices_action_group = NULL;
68
62
 
76
70
void sendto_callback(GObject *widget, gpointer user_data);
77
71
 
78
72
static void action_set_bold (GtkUIManager *manager, GtkAction *action, const char *path);
 
73
static void update_icon_visibility (void);
79
74
 
80
75
void quit_callback(GObject *widget, gpointer user_data)
81
76
{
84
79
 
85
80
void settings_callback(GObject *widget, gpointer user_data)
86
81
{
87
 
        const char *command = "bluetooth-properties";
 
82
        const char *command = "gnome-control-center bluetooth";
88
83
 
89
84
        if (!g_spawn_command_line_async(command, NULL))
90
85
                g_printerr("Couldn't execute command: %s\n", command);
101
96
                                GTK_RESPONSE_ACCEPT, address != NULL);
102
97
}
103
98
 
 
99
static void
 
100
mount_finish_cb (GObject *source_object,
 
101
                 GAsyncResult *res,
 
102
                 gpointer user_data)
 
103
{
 
104
        GError *error = NULL;
 
105
        char *uri;
 
106
 
 
107
        if (bluetooth_applet_browse_address_finish (applet, res, &error) == FALSE) {
 
108
                g_printerr ("Failed to mount OBEX volume: %s", error->message);
 
109
                g_error_free (error);
 
110
                return;
 
111
        }
 
112
 
 
113
        uri = g_file_get_uri (G_FILE (source_object));
 
114
        if (gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, &error) == FALSE) {
 
115
                g_printerr ("Failed to open %s: %s", uri, error->message);
 
116
                g_error_free (error);
 
117
        }
 
118
        g_free (uri);
 
119
}
 
120
 
104
121
void browse_callback(GObject *widget, gpointer user_data)
105
122
{
106
 
        char *address, *cmd;
 
123
        char *address;
107
124
 
108
125
        address = g_strdup (g_object_get_data (widget, "address"));
109
126
        if (address == NULL) {
110
 
                GtkWidget *dialog, *selector;
 
127
                GtkWidget *dialog, *selector, *content_area;
111
128
                int response_id;
112
129
 
113
130
                dialog = gtk_dialog_new_with_buttons(_("Select Device to Browse"), NULL,
114
 
                                                     GTK_DIALOG_NO_SEPARATOR,
 
131
                                                     0,
115
132
                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
116
133
                                                     NULL);
117
134
                gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Browse"), GTK_RESPONSE_ACCEPT);
120
137
                gtk_window_set_default_size(GTK_WINDOW(dialog), 480, 400);
121
138
 
122
139
                gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
123
 
                gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
 
140
                content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
 
141
                gtk_box_set_spacing (GTK_BOX (content_area), 2);
124
142
 
125
143
                selector = bluetooth_chooser_new(_("Select device to browse"));
126
144
                gtk_container_set_border_width(GTK_CONTAINER(selector), 5);
134
152
                             NULL);
135
153
                g_signal_connect(selector, "selected-device-changed",
136
154
                                 G_CALLBACK(select_device_changed), dialog);
137
 
                gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), selector);
 
155
                gtk_container_add (GTK_CONTAINER (content_area), selector);
138
156
 
139
157
                address = NULL;
140
158
                response_id = gtk_dialog_run (GTK_DIALOG (dialog));
147
165
                        return;
148
166
        }
149
167
 
150
 
        cmd = g_strdup_printf("%s --no-default-window \"obex://[%s]\"",
151
 
                              "nautilus", address);
152
 
        g_free (address);
153
 
 
154
 
        if (!g_spawn_command_line_async(cmd, NULL))
155
 
                g_printerr("Couldn't execute command: %s\n", cmd);
156
 
 
157
 
        g_free (cmd);
 
168
        bluetooth_applet_browse_address (applet, address,
 
169
                                         GDK_CURRENT_TIME, mount_finish_cb, NULL);
 
170
 
158
171
}
159
172
 
160
173
void sendto_callback(GObject *widget, gpointer user_data)
161
174
{
162
 
        GPtrArray *a;
163
 
        GError *err = NULL;
164
 
        guint i;
165
175
        const char *address, *alias;
166
176
 
167
177
        address = g_object_get_data (widget, "address");
168
178
        alias = g_object_get_data (widget, "alias");
169
179
 
170
 
        a = g_ptr_array_new ();
171
 
        g_ptr_array_add (a, "bluetooth-sendto");
172
 
        if (address != NULL) {
173
 
                char *s;
174
 
 
175
 
                s = g_strdup_printf ("--device=\"%s\"", address);
176
 
                g_ptr_array_add (a, s);
177
 
        }
178
 
        if (address != NULL && alias != NULL) {
179
 
                char *s;
180
 
 
181
 
                s = g_strdup_printf ("--name=\"%s\"", alias);
182
 
                g_ptr_array_add (a, s);
183
 
        }
184
 
        g_ptr_array_add (a, NULL);
185
 
 
186
 
        if (g_spawn_async(NULL, (char **) a->pdata, NULL,
187
 
                          G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err) == FALSE) {
188
 
                g_printerr("Couldn't execute command: %s\n", err->message);
189
 
                g_error_free (err);
190
 
        }
191
 
 
192
 
        for (i = 1; a->pdata[i] != NULL; i++)
193
 
                g_free (a->pdata[i]);
194
 
 
195
 
        g_ptr_array_free (a, TRUE);
 
180
        bluetooth_applet_send_to_address (applet, address, alias);
196
181
}
197
182
 
198
183
static void keyboard_callback(GObject *widget, gpointer user_data)
211
196
                g_printerr("Couldn't execute command: %s\n", command);
212
197
}
213
198
 
 
199
static void sound_callback(GObject *widget, gpointer user_data)
 
200
{
 
201
        const char *command = SOUND_PREFS;
 
202
 
 
203
        if (!g_spawn_command_line_async(command, NULL))
 
204
                g_printerr("Couldn't execute command: %s\n", command);
 
205
}
 
206
 
214
207
void wizard_callback(GObject *widget, gpointer user_data)
215
208
{
216
209
        const char *command = "bluetooth-wizard";
227
220
        object = gtk_builder_get_object (xml, "killswitch");
228
221
        active = GPOINTER_TO_INT (g_object_get_data (object, "bt-active"));
229
222
        active = !active;
230
 
        bluetooth_killswitch_set_state (killswitch,
231
 
                                        active ? KILLSWITCH_STATE_UNBLOCKED : KILLSWITCH_STATE_SOFT_BLOCKED);
 
223
        bluetooth_applet_set_killswitch_state (applet,
 
224
                                        active ? BLUETOOTH_KILLSWITCH_STATE_UNBLOCKED : BLUETOOTH_KILLSWITCH_STATE_SOFT_BLOCKED);
232
225
        g_object_set_data (object, "bt-active", GINT_TO_POINTER (active));
233
226
}
234
227
 
238
231
        gboolean discoverable;
239
232
 
240
233
        discoverable = gtk_toggle_action_get_active (toggleaction);
241
 
        bluetooth_client_set_discoverable (client, discoverable);
 
234
        discover_lock = TRUE;
 
235
        bluetooth_applet_set_discoverable (applet, discoverable);
 
236
        discover_lock = FALSE;
242
237
}
243
238
 
244
239
static gboolean program_available(const char *program)
268
263
{
269
264
        guint32 activate_time = gtk_get_current_event_time();
270
265
 
271
 
        if (query_blinking() == TRUE) {
272
 
                show_agents();
273
 
                return;
274
 
        }
275
 
 
 
266
        /* Always show the menu, whatever button is pressed.
 
267
         * Agent dialog can be shown from the notification (or should
 
268
         * be shown automatically in the background).
 
269
         */
276
270
        popup_callback(widget, 0, activate_time, user_data);
277
271
}
278
272
 
279
273
static void
280
 
killswitch_state_changed (BluetoothKillswitch *killswitch, KillswitchState state)
 
274
killswitch_state_changed (GObject    *gobject,
 
275
                          GParamSpec *pspec,
 
276
                          gpointer    user_data)
281
277
{
282
278
        GObject *object;
 
279
        BluetoothApplet *applet = BLUETOOTH_APPLET (gobject);
 
280
        BluetoothKillswitchState state = bluetooth_applet_get_killswitch_state (applet);
283
281
        gboolean sensitive = TRUE;
284
282
        gboolean bstate = FALSE;
285
283
        const char *label, *status_label;
286
284
 
287
 
        if (state == KILLSWITCH_STATE_NO_ADAPTER) {
 
285
        if (state == BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER) {
288
286
                object = gtk_builder_get_object (xml, "bluetooth-applet-popup");
289
287
                gtk_menu_popdown (GTK_MENU (object));
 
288
                update_icon_visibility ();
290
289
                return;
291
290
        }
292
291
 
293
 
        if (state == KILLSWITCH_STATE_SOFT_BLOCKED) {
 
292
        if (state == BLUETOOTH_KILLSWITCH_STATE_SOFT_BLOCKED) {
294
293
                label = N_("Turn On Bluetooth");
295
294
                status_label = N_("Bluetooth: Off");
296
295
                bstate = FALSE;
297
 
        } else if (state == KILLSWITCH_STATE_UNBLOCKED) {
 
296
        } else if (state == BLUETOOTH_KILLSWITCH_STATE_UNBLOCKED) {
298
297
                label = N_("Turn Off Bluetooth");
299
298
                status_label = N_("Bluetooth: On");
300
299
                bstate = TRUE;
301
 
        } else if (state == KILLSWITCH_STATE_HARD_BLOCKED) {
 
300
        } else if (state == BLUETOOTH_KILLSWITCH_STATE_HARD_BLOCKED) {
302
301
                sensitive = FALSE;
303
302
                label = NULL;
304
303
                status_label = N_("Bluetooth: Disabled");
321
320
 
322
321
        object = gtk_builder_get_object (xml, "bluetooth-applet-ui-manager");
323
322
        gtk_ui_manager_ensure_update (GTK_UI_MANAGER (object));
 
323
 
 
324
        update_icon_visibility ();
324
325
}
325
326
 
326
327
static GtkWidget *create_popupmenu(void)
346
347
 
347
348
        gtk_builder_connect_signals (xml, NULL);
348
349
 
349
 
        if (bluetooth_killswitch_has_killswitches (killswitch) != FALSE) {
 
350
        if (bluetooth_applet_get_killswitch_state (applet) != BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER) {
350
351
                GObject *object;
351
352
 
352
353
                object = gtk_builder_get_object (xml, "killswitch-label");
373
374
}
374
375
 
375
376
static void
376
 
update_menu_items (void)
 
377
update_menu_items (GObject    *gobject,
 
378
                   GParamSpec *pspec,
 
379
                   gpointer    user_data)
377
380
{
 
381
        BluetoothApplet *applet = BLUETOOTH_APPLET (gobject);
378
382
        gboolean enabled;
379
383
        GObject *object;
380
384
 
381
 
        if (num_adapters_present == 0)
382
 
                enabled = FALSE;
383
 
        else
384
 
                enabled = (num_adapters_present - num_adapters_powered) <= 0;
 
385
        enabled = bluetooth_applet_get_show_full_menu (applet);
385
386
 
386
387
        object = gtk_builder_get_object (xml, "adapter-action-group");
387
388
        gtk_action_group_set_visible (GTK_ACTION_GROUP (object), enabled);
390
391
        if (enabled == FALSE)
391
392
                return;
392
393
 
393
 
        object = gtk_builder_get_object (xml, "browse-device");
394
 
        gtk_action_set_sensitive (GTK_ACTION (object),
395
 
                                  program_available ("nautilus"));
396
 
 
 
394
        gtk_action_group_set_sensitive (GTK_ACTION_GROUP (object), TRUE);
397
395
}
398
396
 
399
397
static void
400
398
update_icon_visibility (void)
401
399
{
402
 
        if (num_adapters_powered == 0)
 
400
        gboolean state = bluetooth_applet_get_killswitch_state (applet);
 
401
        if (state != BLUETOOTH_KILLSWITCH_STATE_UNBLOCKED)
403
402
                set_icon (FALSE);
404
403
        else
405
404
                set_icon (TRUE);
406
405
 
407
406
        if (show_icon_pref != FALSE) {
408
 
                if (num_adapters_present > 0 ||
409
 
                    bluetooth_killswitch_has_killswitches (killswitch) != FALSE) {
 
407
                if (state != BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER) {
410
408
                        show_icon ();
411
409
                        return;
412
410
                }
415
413
}
416
414
 
417
415
static void
418
 
update_discoverability (GtkTreeIter *iter)
 
416
update_discoverability (GObject    *gobject,
 
417
                        GParamSpec *pspec,
 
418
                        gpointer    user_data)
419
419
{
 
420
        BluetoothApplet *applet = BLUETOOTH_APPLET (gobject);
420
421
        gboolean discoverable;
421
422
        GObject *object;
422
423
 
 
424
        /* Avoid loops from changing the UI */
 
425
        if (discover_lock != FALSE)
 
426
                return;
 
427
 
 
428
        discover_lock = TRUE;
 
429
 
423
430
        object = gtk_builder_get_object (xml, "discoverable");
424
431
 
425
 
        if (iter == NULL) {
426
 
                gtk_action_set_visible (GTK_ACTION (object), FALSE);
427
 
                return;
428
 
        }
429
 
 
430
 
        gtk_tree_model_get (devices_model, iter,
431
 
                            BLUETOOTH_COLUMN_DISCOVERABLE, &discoverable,
432
 
                            -1);
 
432
        discoverable = bluetooth_applet_get_discoverable (applet);
433
433
 
434
434
        gtk_action_set_visible (GTK_ACTION (object), TRUE);
435
435
        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (object), discoverable);
 
436
 
 
437
        discover_lock = FALSE;
436
438
}
437
439
 
438
440
static void
477
479
}
478
480
 
479
481
static void
480
 
connection_action_callback (BluetoothClient *_client,
 
482
connection_action_callback (BluetoothApplet *_client,
481
483
                            gboolean success,
482
484
                            gpointer user_data)
483
485
{
486
488
        int connected;
487
489
 
488
490
        /* Revert to the previous state and wait for the
489
 
         * BluetoothClient to catch up */
 
491
         * BluetoothApplet to catch up */
490
492
        connected = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "connected"));
491
493
        if (connected == DISCONNECTING)
492
494
                connected = CONNECTED;
516
518
        path = g_object_get_data (G_OBJECT (action), "device-path");
517
519
 
518
520
        if (connected == DISCONNECTED) {
519
 
                if (bluetooth_client_connect_service (client, path, connection_action_callback, action) != FALSE)
 
521
                if (bluetooth_applet_connect_device (applet, path, connection_action_callback, action) != FALSE)
520
522
                        connected = DISCONNECTING;
521
523
        } else if (connected == CONNECTED) {
522
 
                if (bluetooth_client_disconnect_service (client, path, connection_action_callback, action) != FALSE)
 
524
                if (bluetooth_applet_disconnect_device (applet, path, connection_action_callback, action) != FALSE)
523
525
                        connected = CONNECTING;
524
526
        } else {
525
527
                g_assert_not_reached ();
547
549
 
548
550
        label = gtk_action_get_label (action);
549
551
        str = g_strdup_printf ("<b>%s</b>", label);
550
 
        gtk_label_set_markup (GTK_LABEL (GTK_BIN (widget)->child), str);
 
552
        gtk_label_set_markup (GTK_LABEL (gtk_bin_get_child (GTK_BIN (widget))), str);
551
553
        g_free (str);
552
554
}
553
555
 
589
591
}
590
592
 
591
593
static gboolean
592
 
device_has_uuid (const char **uuids, const char *uuid)
593
 
{
594
 
        guint i;
595
 
 
596
 
        if (uuids == NULL)
597
 
                return FALSE;
598
 
 
599
 
        for (i = 0; uuids[i] != NULL; i++) {
600
 
                if (g_str_equal (uuid, uuids[i]) != FALSE)
601
 
                        return TRUE;
602
 
        }
603
 
        return FALSE;
604
 
}
605
 
 
606
 
static gboolean
607
 
device_has_submenu (const char **uuids, GHashTable *services, BluetoothType type)
608
 
{
609
 
        if (services != NULL)
610
 
                return TRUE;
611
 
        if (device_has_uuid (uuids, "OBEXObjectPush") != FALSE)
612
 
                return TRUE;
613
 
        if (device_has_uuid (uuids, "OBEXFileTransfer") != FALSE)
614
 
                return TRUE;
615
 
        if (type == BLUETOOTH_TYPE_KEYBOARD ||
616
 
            type == BLUETOOTH_TYPE_MOUSE)
617
 
                return TRUE;
 
594
device_has_submenu (BluetoothSimpleDevice *dev)
 
595
{
 
596
        if (dev->can_connect != FALSE)
 
597
                return TRUE;
 
598
        if (dev->capabilities != BLUETOOTH_CAPABILITIES_NONE)
 
599
                return TRUE;
618
600
        return FALSE;
619
601
}
620
602
 
678
660
}
679
661
 
680
662
static void
681
 
update_device_list (GtkTreeIter *parent)
 
663
update_device_list (BluetoothApplet *applet,
 
664
                                        gpointer user_data)
682
665
{
683
666
        GtkUIManager *uimanager;
684
 
        GtkTreeIter iter;
685
 
        gboolean cont;
686
 
        guint num_devices;
687
 
        GList *actions, *l;
688
 
 
689
 
        num_devices = 0;
 
667
        GList *actions, *devices, *l;
 
668
        gboolean has_devices = FALSE;
690
669
 
691
670
        uimanager = GTK_UI_MANAGER (gtk_builder_get_object (xml, "bluetooth-applet-ui-manager"));
692
671
 
693
 
        if (parent == NULL) {
694
 
                /* No default adapter? Remove everything */
 
672
        devices = bluetooth_applet_get_devices (applet);
 
673
 
 
674
        if (devices == NULL) {
 
675
                /* No devices? Remove everything */
695
676
                actions = gtk_action_group_list_actions (devices_action_group);
696
677
                g_list_foreach (actions, (GFunc) remove_action_item, uimanager);
697
678
                g_list_free (actions);
707
688
        }
708
689
        actions = g_list_remove_all (actions, NULL);
709
690
 
710
 
        cont = gtk_tree_model_iter_children (devices_model, &iter, parent);
711
 
        while (cont) {
712
 
                GHashTable *services;
713
 
                DBusGProxy *proxy;
714
 
                char *alias, *address, **uuids, *name;
715
 
                gboolean is_connected;
716
 
                BluetoothType type;
 
691
        for (l = devices; l != NULL; l = g_list_next (l)) {
 
692
                BluetoothSimpleDevice *device = l->data;
717
693
                GtkAction *action, *status, *oper;
718
 
 
719
 
                gtk_tree_model_get (devices_model, &iter,
720
 
                                    BLUETOOTH_COLUMN_PROXY, &proxy,
721
 
                                    BLUETOOTH_COLUMN_ADDRESS, &address,
722
 
                                    BLUETOOTH_COLUMN_SERVICES, &services,
723
 
                                    BLUETOOTH_COLUMN_ALIAS, &alias,
724
 
                                    BLUETOOTH_COLUMN_UUIDS, &uuids,
725
 
                                    BLUETOOTH_COLUMN_TYPE, &type,
726
 
                                    -1);
727
 
 
728
 
                if (device_has_submenu ((const char **) uuids, services, type) == FALSE ||
729
 
                    address == NULL || proxy == NULL || alias == NULL) {
730
 
                        if (proxy != NULL)
731
 
                                g_object_unref (proxy);
732
 
 
733
 
                        if (services != NULL)
734
 
                                g_hash_table_unref (services);
735
 
                        g_strfreev (uuids);
736
 
                        g_free (alias);
737
 
                        g_free (address);
738
 
                        cont = gtk_tree_model_iter_next (devices_model, &iter);
 
694
                char *name;
 
695
 
 
696
                if (device_has_submenu (device) == FALSE) {
 
697
                        g_boxed_free (BLUETOOTH_TYPE_SIMPLE_DEVICE, device);
739
698
                        continue;
740
699
                }
741
700
 
742
 
                action = gtk_action_group_get_action (devices_action_group, address);
 
701
                has_devices = TRUE;
 
702
 
 
703
                action = gtk_action_group_get_action (devices_action_group, device->bdaddr);
743
704
                oper = NULL;
744
705
                status = NULL;
745
706
                if (action) {
747
708
 
748
709
                        actions = g_list_remove (actions, action);
749
710
 
750
 
                        action_name = g_strdup_printf ("%s-status", address);
 
711
                        action_name = g_strdup_printf ("%s-status", device->bdaddr);
751
712
                        status = gtk_action_group_get_action (devices_action_group, action_name);
752
713
                        g_free (action_name);
753
714
 
754
 
                        action_name = g_strdup_printf ("%s-action", address);
 
715
                        action_name = g_strdup_printf ("%s-action", device->bdaddr);
755
716
                        oper = gtk_action_group_get_action (devices_action_group, action_name);
756
717
                        g_free (action_name);
757
718
                }
758
719
 
759
 
                /* If one service is connected, then we're connected */
760
 
                is_connected = FALSE;
761
 
                if (services != NULL) {
762
 
                        GList *list, *l;
763
 
 
764
 
                        list = g_hash_table_get_values (services);
765
 
                        for (l = list; l != NULL; l = l->next) {
766
 
                                BluetoothStatus val = GPOINTER_TO_INT (l->data);
767
 
                                if (val == BLUETOOTH_STATUS_CONNECTED ||
768
 
                                    val == BLUETOOTH_STATUS_PLAYING) {
769
 
                                        is_connected = TRUE;
770
 
                                        break;
771
 
                                }
772
 
                        }
773
 
                        g_list_free (list);
774
 
                }
775
 
 
776
 
                name = escape_label_for_action (alias);
 
720
                name = escape_label_for_action (device->alias);
777
721
 
778
722
                if (action == NULL) {
779
723
                        guint menu_merge_id;
780
724
                        char *action_path;
781
725
 
782
726
                        /* The menu item with descendants */
783
 
                        action = gtk_action_new (address, name, NULL, NULL);
 
727
                        action = gtk_action_new (device->bdaddr, name, NULL, NULL);
784
728
 
785
729
                        gtk_action_group_add_action (devices_action_group, action);
786
730
                        g_object_unref (action);
787
731
                        menu_merge_id = gtk_ui_manager_new_merge_id (uimanager);
788
732
                        gtk_ui_manager_add_ui (uimanager, menu_merge_id,
789
 
                                               "/bluetooth-applet-popup/devices-placeholder", address, address,
 
733
                                               "/bluetooth-applet-popup/devices-placeholder", device->bdaddr, device->bdaddr,
790
734
                                               GTK_UI_MANAGER_MENU, FALSE);
791
735
                        g_object_set_data_full (G_OBJECT (action),
792
736
                                                "merge-id", GUINT_TO_POINTER (menu_merge_id), NULL);
793
737
 
794
738
                        /* The status menu item */
795
 
                        status = add_menu_item (address,
 
739
                        status = add_menu_item (device->bdaddr,
796
740
                                                "status",
797
 
                                                is_connected ? _("Connected") : _("Disconnected"),
 
741
                                                device->connected ? _("Connected") : _("Disconnected"),
798
742
                                                uimanager,
799
743
                                                menu_merge_id,
800
744
                                                NULL);
801
745
                        gtk_action_set_sensitive (status, FALSE);
802
746
 
803
 
                        if (services != NULL) {
 
747
                        if (device->can_connect) {
804
748
                                action_path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s/%s-status",
805
 
                                                               address, address);
 
749
                                                               device->bdaddr, device->bdaddr);
806
750
                                action_set_bold (uimanager, status, action_path);
807
751
                                g_free (action_path);
808
752
                        } else {
810
754
                        }
811
755
 
812
756
                        /* The connect button */
813
 
                        oper = add_menu_item (address,
 
757
                        oper = add_menu_item (device->bdaddr,
814
758
                                              "action",
815
 
                                              is_connected ? _("Disconnect") : _("Connect"),
 
759
                                              device->connected ? _("Disconnect") : _("Connect"),
816
760
                                              uimanager,
817
761
                                              menu_merge_id,
818
762
                                              G_CALLBACK (on_connect_activate));
819
 
                        if (services == NULL)
 
763
                        if (!device->can_connect)
820
764
                                gtk_action_set_visible (oper, FALSE);
821
765
 
822
 
                        add_separator_item (address, "connect-sep", uimanager, menu_merge_id);
 
766
                        add_separator_item (device->bdaddr, "connect-sep", uimanager, menu_merge_id);
823
767
 
824
768
                        /* The Send to... button */
825
 
                        if (device_has_uuid ((const char **) uuids, "OBEXObjectPush") != FALSE) {
826
 
                                add_menu_item (address,
 
769
                        if (device->capabilities & BLUETOOTH_CAPABILITIES_OBEX_PUSH) {
 
770
                                add_menu_item (device->bdaddr,
827
771
                                               "sendto",
828
772
                                               _("Send files..."),
829
773
                                               uimanager,
830
774
                                               menu_merge_id,
831
775
                                               G_CALLBACK (sendto_callback));
832
776
                                g_object_set_data_full (G_OBJECT (action),
833
 
                                                        "alias", g_strdup (alias), g_free);
 
777
                                                        "alias", g_strdup (device->alias), g_free);
834
778
                        }
835
 
                        if (device_has_uuid ((const char **) uuids, "OBEXFileTransfer") != FALSE) {
836
 
                                add_menu_item (address,
 
779
                        if (device->capabilities & BLUETOOTH_CAPABILITIES_OBEX_FILE_TRANSFER) {
 
780
                                add_menu_item (device->bdaddr,
837
781
                                               "browse",
838
782
                                               _("Browse files..."),
839
783
                                               uimanager,
841
785
                                               G_CALLBACK (browse_callback));
842
786
                        }
843
787
 
844
 
                        add_separator_item (address, "files-sep", uimanager, menu_merge_id);
 
788
                        add_separator_item (device->bdaddr, "files-sep", uimanager, menu_merge_id);
845
789
 
846
 
                        if (type == BLUETOOTH_TYPE_KEYBOARD && program_available (KEYBOARD_PREFS)) {
847
 
                                add_menu_item (address,
 
790
                        if (device->type == BLUETOOTH_TYPE_KEYBOARD && program_available (GNOMECC)) {
 
791
                                add_menu_item (device->bdaddr,
848
792
                                               "keyboard",
849
793
                                               _("Open Keyboard Preferences..."),
850
794
                                               uimanager,
851
795
                                               menu_merge_id,
852
796
                                               G_CALLBACK (keyboard_callback));
853
797
                        }
854
 
                        if (type == BLUETOOTH_TYPE_MOUSE && program_available (MOUSE_PREFS)) {
855
 
                                add_menu_item (address,
 
798
                        if (device->type == BLUETOOTH_TYPE_MOUSE && program_available (GNOMECC)) {
 
799
                                add_menu_item (device->bdaddr,
856
800
                                               "mouse",
857
801
                                               _("Open Mouse Preferences..."),
858
802
                                               uimanager,
859
803
                                               menu_merge_id,
860
804
                                               G_CALLBACK (mouse_callback));
861
805
                        }
 
806
                        if ((device->type == BLUETOOTH_TYPE_HEADSET ||
 
807
                             device->type == BLUETOOTH_TYPE_HEADPHONES ||
 
808
                             device->type == BLUETOOTH_TYPE_OTHER_AUDIO) && program_available (GNOMECC)) {
 
809
                                add_menu_item (device->bdaddr,
 
810
                                               "sound",
 
811
                                               _("Open Sound Preferences..."),
 
812
                                               uimanager,
 
813
                                               menu_merge_id,
 
814
                                               G_CALLBACK (sound_callback));
 
815
                        }
862
816
                } else {
863
817
                        gtk_action_set_label (action, name);
864
818
 
865
 
                        gtk_action_set_visible (status, services != NULL);
866
 
                        gtk_action_set_visible (oper, services != NULL);
867
 
                        if (services != NULL) {
868
 
                                set_device_status_label (address, is_connected ? CONNECTED : DISCONNECTED);
869
 
                                gtk_action_set_label (oper, is_connected ? _("Disconnect") : _("Connect"));
 
819
                        if (device->can_connect) {
 
820
                                gtk_action_set_visible (status, TRUE);
 
821
                                gtk_action_set_visible (oper, TRUE);
 
822
                                set_device_status_label (device->bdaddr, device->connected ? CONNECTED : DISCONNECTED);
 
823
                                gtk_action_set_label (oper, device->connected ? _("Disconnect") : _("Connect"));
 
824
                        } else {
 
825
                                gtk_action_set_visible (status, FALSE);
 
826
                                gtk_action_set_visible (oper, FALSE);
870
827
                        }
871
828
                }
872
829
                g_free (name);
873
830
 
874
831
                if (oper != NULL) {
875
832
                        g_object_set_data_full (G_OBJECT (oper),
876
 
                                                "connected", GINT_TO_POINTER (is_connected ? CONNECTED : DISCONNECTED), NULL);
 
833
                                                "connected", GINT_TO_POINTER (device->connected ? CONNECTED : DISCONNECTED), NULL);
877
834
                        g_object_set_data_full (G_OBJECT (oper),
878
 
                                                "device-path", g_strdup (dbus_g_proxy_get_path (proxy)), g_free);
 
835
                                                "device-path", g_strdup (device->device_path), g_free);
879
836
                }
880
837
 
881
838
                /* And now for the trick of the day */
882
 
                if (is_connected != FALSE) {
 
839
                if (device->connected != FALSE) {
883
840
                        char *path;
884
841
 
885
 
                        path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s", address);
 
842
                        path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s", device->bdaddr);
886
843
                        action_set_bold (uimanager, action, path);
887
844
                        g_free (path);
888
845
                }
889
846
 
890
 
                num_devices++;
891
 
 
892
 
                if (proxy != NULL)
893
 
                        g_object_unref (proxy);
894
 
 
895
 
                if (services != NULL)
896
 
                        g_hash_table_unref (services);
897
 
                g_strfreev (uuids);
898
 
                g_free (alias);
899
 
                g_free (address);
900
 
                cont = gtk_tree_model_iter_next (devices_model, &iter);
 
847
                g_boxed_free (BLUETOOTH_TYPE_SIMPLE_DEVICE, device);
901
848
        }
902
849
 
903
850
        /* Remove the left-over devices */
904
851
        g_list_foreach (actions, (GFunc) remove_action_item, uimanager);
905
852
        g_list_free (actions);
906
853
 
 
854
        /* Cleanup */
 
855
        g_list_free (devices);
907
856
done:
908
857
        gtk_ui_manager_ensure_update (uimanager);
909
858
 
910
859
        gtk_action_set_visible (GTK_ACTION (gtk_builder_get_object (xml, "devices-label")),
911
 
                                num_devices > 0);
912
 
}
913
 
 
914
 
static void device_changed (GtkTreeModel *model,
915
 
                             GtkTreePath  *path,
916
 
                             GtkTreeIter  *_iter,
917
 
                             gpointer      data)
918
 
{
919
 
        GtkTreeIter iter, *default_iter;
920
 
        gboolean powered, cont;
921
 
 
922
 
        default_iter = NULL;
923
 
        num_adapters_present = num_adapters_powered = 0;
924
 
 
925
 
        cont = gtk_tree_model_get_iter_first (model, &iter);
926
 
        while (cont) {
927
 
                gboolean is_default;
928
 
 
929
 
                num_adapters_present++;
930
 
 
931
 
                gtk_tree_model_get (model, &iter,
932
 
                                    BLUETOOTH_COLUMN_DEFAULT, &is_default,
933
 
                                    BLUETOOTH_COLUMN_POWERED, &powered,
934
 
                                    -1);
935
 
                if (powered)
936
 
                        num_adapters_powered++;
937
 
                if (is_default && powered)
938
 
                        default_iter = gtk_tree_iter_copy (&iter);
939
 
 
940
 
                cont = gtk_tree_model_iter_next (model, &iter);
941
 
        }
942
 
 
943
 
        update_discoverability (default_iter);
944
 
        update_icon_visibility ();
945
 
        update_menu_items ();
946
 
        update_device_list (default_iter);
947
 
 
948
 
        if (default_iter != NULL)
949
 
                gtk_tree_iter_free (default_iter);
950
 
}
951
 
 
952
 
static void device_added(GtkTreeModel *model,
953
 
                          GtkTreePath *path,
954
 
                          GtkTreeIter *iter,
955
 
                          gpointer user_data)
956
 
{
957
 
        device_changed (model, path, iter, user_data);
958
 
}
959
 
 
960
 
static void device_removed(GtkTreeModel *model,
961
 
                            GtkTreePath *path,
962
 
                            gpointer user_data)
963
 
{
964
 
        device_changed (model, path, NULL, user_data);
965
 
}
966
 
 
967
 
static void gconf_callback(GConfClient *client, guint cnxn_id,
968
 
                                        GConfEntry *entry, gpointer user_data)
969
 
{
970
 
        GConfValue *value;
971
 
 
972
 
        value = gconf_entry_get_value(entry);
973
 
        if (value == NULL)
974
 
                return;
975
 
 
976
 
        if (g_str_equal(entry->key, PREF_SHOW_ICON) == TRUE) {
977
 
                show_icon_pref = gconf_value_get_bool(value);
978
 
                update_icon_visibility();
979
 
                return;
980
 
        }
 
860
                                has_devices);
 
861
}
 
862
 
 
863
static void
 
864
show_icon_changed (GSettings *settings,
 
865
                   const char *key,
 
866
                   gpointer   user_data)
 
867
{
 
868
        show_icon_pref = g_settings_get_boolean (settings, PREF_SHOW_ICON);
 
869
        update_icon_visibility();
981
870
}
982
871
 
983
872
static GOptionEntry options[] = {
987
876
 
988
877
int main(int argc, char *argv[])
989
878
{
990
 
        UniqueApp *app;
 
879
        GApplication *app;
991
880
        GtkStatusIcon *statusicon;
992
881
        GtkWidget *menu;
993
 
        GConfValue *value;
994
882
        GOptionContext *context;
995
883
        GError *error = NULL;
996
884
 
1013
901
        }
1014
902
 
1015
903
        if (option_debug == FALSE) {
1016
 
                app = unique_app_new ("org.gnome.Bluetooth.applet", NULL);
1017
 
                if (unique_app_is_running (app)) {
1018
 
                        gdk_notify_startup_complete ();
 
904
                GError *error = NULL;
 
905
 
 
906
                app = g_application_new ("org.gnome.Bluetooth.applet",
 
907
                                         G_APPLICATION_FLAGS_NONE);
 
908
                if (!g_application_register (app, NULL, &error)) {
 
909
                        g_object_unref (app);
 
910
                        g_warning ("%s", error->message);
 
911
                        g_error_free (error);
 
912
                        return 1;
 
913
                }
 
914
                if (g_application_get_is_remote (app)) {
 
915
                        g_object_unref (app);
1019
916
                        g_warning ("Applet is already running, exiting");
1020
917
                        return 0;
1021
918
                }
1027
924
 
1028
925
        gtk_window_set_default_icon_name("bluetooth");
1029
926
 
1030
 
        killswitch = bluetooth_killswitch_new ();
1031
 
        g_signal_connect (G_OBJECT (killswitch), "state-changed",
1032
 
                          G_CALLBACK (killswitch_state_changed), NULL);
 
927
        applet = g_object_new (BLUETOOTH_TYPE_APPLET, NULL);
 
928
        g_signal_connect (G_OBJECT (applet), "notify::killswitch-state",
 
929
                        G_CALLBACK (killswitch_state_changed), NULL);
1033
930
 
1034
931
        menu = create_popupmenu();
1035
932
 
1036
 
        client = bluetooth_client_new();
1037
 
 
1038
 
        devices_model = bluetooth_client_get_model(client);
1039
 
 
1040
 
        g_signal_connect(G_OBJECT(devices_model), "row-inserted",
1041
 
                         G_CALLBACK(device_added), NULL);
1042
 
        g_signal_connect(G_OBJECT(devices_model), "row-deleted",
1043
 
                         G_CALLBACK(device_removed), NULL);
1044
 
        g_signal_connect (G_OBJECT (devices_model), "row-changed",
1045
 
                          G_CALLBACK (device_changed), NULL);
1046
 
        /* Set the default */
1047
 
        device_changed (devices_model, NULL, NULL, NULL);
1048
 
        if (bluetooth_killswitch_has_killswitches (killswitch) != FALSE) {
1049
 
                killswitch_state_changed (killswitch,
1050
 
                                          bluetooth_killswitch_get_state (killswitch));
1051
 
        }
1052
 
 
1053
 
        gconf = gconf_client_get_default();
1054
 
 
1055
 
        value = gconf_client_get (gconf, PREF_SHOW_ICON, NULL);
1056
 
        if (value == NULL) {
1057
 
                show_icon_pref = TRUE;
1058
 
        } else {
1059
 
                show_icon_pref = gconf_value_get_bool (value);
1060
 
                gconf_value_free (value);
1061
 
        }
1062
 
 
1063
 
        gconf_client_add_dir(gconf, PREF_DIR, GCONF_CLIENT_PRELOAD_NONE, NULL);
1064
 
 
1065
 
        gconf_client_notify_add(gconf, PREF_DIR,
1066
 
                                        gconf_callback, NULL, NULL, NULL);
 
933
        g_signal_connect (G_OBJECT (applet), "devices-changed",
 
934
                        G_CALLBACK (update_device_list), NULL);
 
935
        g_signal_connect (G_OBJECT (applet), "notify::discoverable",
 
936
                        G_CALLBACK (update_discoverability), NULL);
 
937
        g_signal_connect (G_OBJECT (applet), "notify::show-full-menu",
 
938
                        G_CALLBACK (update_menu_items), NULL);
 
939
 
 
940
        killswitch_state_changed ((GObject*) applet, NULL, NULL);
 
941
        update_menu_items ((GObject*) applet, NULL, NULL);
 
942
        update_discoverability ((GObject*) applet, NULL, NULL);
 
943
        update_device_list (applet, NULL);
 
944
 
 
945
        settings = g_settings_new (SCHEMA_NAME);
 
946
        show_icon_pref = g_settings_get_boolean (settings, PREF_SHOW_ICON);
 
947
 
 
948
        g_signal_connect (G_OBJECT (settings), "changed::" PREF_SHOW_ICON,
 
949
                          G_CALLBACK (show_icon_changed), NULL);
1067
950
 
1068
951
        statusicon = init_notification();
1069
952
 
1074
957
        g_signal_connect(statusicon, "popup-menu",
1075
958
                                G_CALLBACK(popup_callback), menu);
1076
959
 
1077
 
        setup_agents();
 
960
        setup_agents(applet);
1078
961
 
1079
962
        gtk_main();
1080
963
 
1081
964
        gtk_widget_destroy(menu);
1082
965
 
1083
 
        g_object_unref(gconf);
1084
 
 
1085
 
        cleanup_agents();
 
966
        g_object_unref(settings);
1086
967
 
1087
968
        cleanup_notification();
1088
969
 
1089
 
        g_object_unref(devices_model);
1090
 
 
1091
 
        g_object_unref(client);
 
970
        g_object_unref(applet);
1092
971
 
1093
972
        if (app != NULL)
1094
973
                g_object_unref (app);