static void on_connect_activate (GtkAction *action, gpointer data) { int connected; const char *path; const char *address; connected = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "connected")); /* Don't try connecting if something is already in progress */ if (connected == CONNECTING || connected == DISCONNECTING) return; path = g_object_get_data (G_OBJECT (action), "device-path"); if (connected == DISCONNECTED) { if (bluetooth_applet_connect_device (applet, path, connection_action_callback, action) != FALSE) connected = DISCONNECTING; } else if (connected == CONNECTED) { if (bluetooth_applet_disconnect_device (applet, path, connection_action_callback, action) != FALSE) connected = CONNECTING; } else { g_assert_not_reached (); } g_object_set_data_full (G_OBJECT (action), "connected", GINT_TO_POINTER (connected), NULL); address = g_object_get_data (G_OBJECT (action), "address"); set_device_status_label (address, connected); }
static void connection_action_callback (BluetoothApplet *_client, gboolean success, gpointer user_data) { GtkAction *action = (GtkAction *) user_data; const char *address; int connected; /* Revert to the previous state and wait for the * BluetoothApplet to catch up */ connected = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action), "connected")); if (connected == DISCONNECTING) connected = CONNECTED; else if (connected == CONNECTING) connected = DISCONNECTED; else return; g_object_set_data_full (G_OBJECT (action), "connected", GINT_TO_POINTER (connected), NULL); address = g_object_get_data (G_OBJECT (action), "address"); set_device_status_label (address, connected); }
static void update_device_list (BluetoothApplet *applet, gpointer user_data) { GtkUIManager *uimanager; GList *actions, *devices, *l; gboolean has_devices = FALSE; uimanager = GTK_UI_MANAGER (gtk_builder_get_object (xml, "bluetooth-applet-ui-manager")); devices = bluetooth_applet_get_devices (applet); if (devices == NULL) { /* No devices? Remove everything */ actions = gtk_action_group_list_actions (devices_action_group); g_list_foreach (actions, (GFunc) remove_action_item, uimanager); g_list_free (actions); goto done; } /* Get a list of actions, and we'll remove the ones with a * device in the list. We remove the submenu items first */ actions = gtk_action_group_list_actions (devices_action_group); for (l = actions; l != NULL; l = l->next) { if (bluetooth_verify_address (gtk_action_get_name (l->data)) == FALSE) l->data = NULL; } actions = g_list_remove_all (actions, NULL); for (l = devices; l != NULL; l = g_list_next (l)) { BluetoothSimpleDevice *device = l->data; GtkAction *action, *status, *oper; char *name; if (device_has_submenu (device) == FALSE) { g_boxed_free (BLUETOOTH_TYPE_SIMPLE_DEVICE, device); continue; } has_devices = TRUE; action = gtk_action_group_get_action (devices_action_group, device->bdaddr); oper = NULL; status = NULL; if (action) { char *action_name; actions = g_list_remove (actions, action); action_name = g_strdup_printf ("%s-status", device->bdaddr); status = gtk_action_group_get_action (devices_action_group, action_name); g_free (action_name); action_name = g_strdup_printf ("%s-action", device->bdaddr); oper = gtk_action_group_get_action (devices_action_group, action_name); g_free (action_name); } name = escape_label_for_action (device->alias); if (action == NULL) { guint menu_merge_id; char *action_path; /* The menu item with descendants */ action = gtk_action_new (device->bdaddr, name, NULL, NULL); gtk_action_group_add_action (devices_action_group, action); g_object_unref (action); menu_merge_id = gtk_ui_manager_new_merge_id (uimanager); gtk_ui_manager_add_ui (uimanager, menu_merge_id, "/bluetooth-applet-popup/devices-placeholder", device->bdaddr, device->bdaddr, GTK_UI_MANAGER_MENU, FALSE); g_object_set_data_full (G_OBJECT (action), "merge-id", GUINT_TO_POINTER (menu_merge_id), NULL); /* The status menu item */ status = add_menu_item (device->bdaddr, "status", device->connected ? _("Connected") : _("Disconnected"), uimanager, menu_merge_id, NULL); gtk_action_set_sensitive (status, FALSE); if (device->can_connect) { action_path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s/%s-status", device->bdaddr, device->bdaddr); action_set_bold (uimanager, status, action_path); g_free (action_path); } else { gtk_action_set_visible (status, FALSE); } /* The connect button */ oper = add_menu_item (device->bdaddr, "action", device->connected ? _("Disconnect") : _("Connect"), uimanager, menu_merge_id, G_CALLBACK (on_connect_activate)); if (!device->can_connect) gtk_action_set_visible (oper, FALSE); add_separator_item (device->bdaddr, "connect-sep", uimanager, menu_merge_id); /* The Send to... button */ if (device->capabilities & BLUETOOTH_CAPABILITIES_OBEX_PUSH) { add_menu_item (device->bdaddr, "sendto", _("Send files..."), uimanager, menu_merge_id, G_CALLBACK (sendto_callback)); g_object_set_data_full (G_OBJECT (action), "alias", g_strdup (device->alias), g_free); } if (device->capabilities & BLUETOOTH_CAPABILITIES_OBEX_FILE_TRANSFER) { add_menu_item (device->bdaddr, "browse", _("Browse files..."), uimanager, menu_merge_id, G_CALLBACK (browse_callback)); } add_separator_item (device->bdaddr, "files-sep", uimanager, menu_merge_id); if (device->type == BLUETOOTH_TYPE_KEYBOARD && program_available (GNOMECC)) { add_menu_item (device->bdaddr, "keyboard", _("Keyboard Settings"), uimanager, menu_merge_id, G_CALLBACK (keyboard_callback)); } if (device->type == BLUETOOTH_TYPE_MOUSE && program_available (GNOMECC)) { add_menu_item (device->bdaddr, "mouse", _("Mouse and Touchpad Settings"), uimanager, menu_merge_id, G_CALLBACK (mouse_callback)); } if ((device->type == BLUETOOTH_TYPE_HEADSET || device->type == BLUETOOTH_TYPE_HEADPHONES || device->type == BLUETOOTH_TYPE_OTHER_AUDIO) && program_available (GNOMECC)) { add_menu_item (device->bdaddr, "sound", _("Sound Settings"), uimanager, menu_merge_id, G_CALLBACK (sound_callback)); } } else { gtk_action_set_label (action, name); if (device->can_connect) { gtk_action_set_visible (status, TRUE); gtk_action_set_visible (oper, TRUE); set_device_status_label (device->bdaddr, device->connected ? CONNECTED : DISCONNECTED); gtk_action_set_label (oper, device->connected ? _("Disconnect") : _("Connect")); } else { gtk_action_set_visible (status, FALSE); gtk_action_set_visible (oper, FALSE); } } g_free (name); if (oper != NULL) { g_object_set_data_full (G_OBJECT (oper), "connected", GINT_TO_POINTER (device->connected ? CONNECTED : DISCONNECTED), NULL); g_object_set_data_full (G_OBJECT (oper), "device-path", g_strdup (device->device_path), g_free); } /* And now for the trick of the day */ if (device->connected != FALSE) { char *path; path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s", device->bdaddr); action_set_bold (uimanager, action, path); g_free (path); } g_boxed_free (BLUETOOTH_TYPE_SIMPLE_DEVICE, device); } /* Remove the left-over devices */ g_list_foreach (actions, (GFunc) remove_action_item, uimanager); g_list_free (actions); /* Cleanup */ g_list_free (devices); done: gtk_ui_manager_ensure_update (uimanager); gtk_action_set_visible (GTK_ACTION (gtk_builder_get_object (xml, "devices-label")), has_devices); }
static void update_device_list (GtkTreeIter *parent) { GtkUIManager *uimanager; GtkTreeIter iter; gboolean cont; guint num_devices; GList *actions, *l; num_devices = 0; uimanager = GTK_UI_MANAGER (gtk_builder_get_object (xml, "bluetooth-applet-ui-manager")); if (parent == NULL) { /* No default adapter? Remove everything */ actions = gtk_action_group_list_actions (devices_action_group); g_list_foreach (actions, (GFunc) remove_action_item, uimanager); g_list_free (actions); goto done; } /* Get a list of actions, and we'll remove the ones with a * device in the list. We remove the submenu items first */ actions = gtk_action_group_list_actions (devices_action_group); for (l = actions; l != NULL; l = l->next) { if (bluetooth_verify_address (gtk_action_get_name (l->data)) == FALSE) l->data = NULL; } actions = g_list_remove_all (actions, NULL); cont = gtk_tree_model_iter_children (devices_model, &iter, parent); while (cont) { GHashTable *services; DBusGProxy *proxy; char *alias, *address, **uuids, *name; gboolean is_connected; BluetoothType type; GtkAction *action, *status, *oper; gtk_tree_model_get (devices_model, &iter, BLUETOOTH_COLUMN_PROXY, &proxy, BLUETOOTH_COLUMN_ADDRESS, &address, BLUETOOTH_COLUMN_SERVICES, &services, BLUETOOTH_COLUMN_ALIAS, &alias, BLUETOOTH_COLUMN_UUIDS, &uuids, BLUETOOTH_COLUMN_TYPE, &type, -1); if (device_has_submenu ((const char **) uuids, services, type) == FALSE || address == NULL || proxy == NULL || alias == NULL) { if (proxy != NULL) g_object_unref (proxy); if (services != NULL) g_hash_table_unref (services); g_strfreev (uuids); g_free (alias); g_free (address); cont = gtk_tree_model_iter_next (devices_model, &iter); continue; } action = gtk_action_group_get_action (devices_action_group, address); oper = NULL; status = NULL; if (action) { char *action_name; actions = g_list_remove (actions, action); action_name = g_strdup_printf ("%s-status", address); status = gtk_action_group_get_action (devices_action_group, action_name); g_free (action_name); action_name = g_strdup_printf ("%s-action", address); oper = gtk_action_group_get_action (devices_action_group, action_name); g_free (action_name); } /* If one service is connected, then we're connected */ is_connected = FALSE; if (services != NULL) { 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) { is_connected = TRUE; break; } } g_list_free (list); } name = escape_label_for_action (alias); if (action == NULL) { guint menu_merge_id; char *action_path; /* The menu item with descendants */ action = gtk_action_new (address, name, NULL, NULL); gtk_action_group_add_action (devices_action_group, action); g_object_unref (action); menu_merge_id = gtk_ui_manager_new_merge_id (uimanager); gtk_ui_manager_add_ui (uimanager, menu_merge_id, "/bluetooth-applet-popup/devices-placeholder", address, address, GTK_UI_MANAGER_MENU, FALSE); g_object_set_data_full (G_OBJECT (action), "merge-id", GUINT_TO_POINTER (menu_merge_id), NULL); /* The status menu item */ status = add_menu_item (address, "status", is_connected ? _("Connected") : _("Disconnected"), uimanager, menu_merge_id, NULL); gtk_action_set_sensitive (status, FALSE); if (services != NULL) { action_path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s/%s-status", address, address); action_set_bold (uimanager, status, action_path); g_free (action_path); } else { gtk_action_set_visible (status, FALSE); } /* The connect button */ oper = add_menu_item (address, "action", is_connected ? _("Disconnect") : _("Connect"), uimanager, menu_merge_id, G_CALLBACK (on_connect_activate)); if (services == NULL) gtk_action_set_visible (oper, FALSE); add_separator_item (address, "connect-sep", uimanager, menu_merge_id); /* The Send to... button */ if (device_has_uuid ((const char **) uuids, "OBEXObjectPush") != FALSE) { add_menu_item (address, "sendto", _("Send files..."), uimanager, menu_merge_id, G_CALLBACK (sendto_callback)); g_object_set_data_full (G_OBJECT (action), "alias", g_strdup (alias), g_free); } if (device_has_uuid ((const char **) uuids, "OBEXFileTransfer") != FALSE) { add_menu_item (address, "browse", _("Browse files..."), uimanager, menu_merge_id, G_CALLBACK (browse_callback)); } add_separator_item (address, "files-sep", uimanager, menu_merge_id); if (type == BLUETOOTH_TYPE_KEYBOARD && program_available (KEYBOARD_PREFS)) { add_menu_item (address, "keyboard", _("Open Keyboard Preferences..."), uimanager, menu_merge_id, G_CALLBACK (keyboard_callback)); } if (type == BLUETOOTH_TYPE_MOUSE && program_available (MOUSE_PREFS)) { add_menu_item (address, "mouse", _("Open Mouse Preferences..."), uimanager, menu_merge_id, G_CALLBACK (mouse_callback)); } if ((type == BLUETOOTH_TYPE_HEADSET || type == BLUETOOTH_TYPE_HEADPHONES || type == BLUETOOTH_TYPE_OTHER_AUDIO) && program_available (SOUND_PREFS)) { add_menu_item (address, "sound", _("Open Sound Preferences..."), uimanager, menu_merge_id, G_CALLBACK (sound_callback)); } } else { gtk_action_set_label (action, name); gtk_action_set_visible (status, services != NULL); gtk_action_set_visible (oper, services != NULL); if (services != NULL) { set_device_status_label (address, is_connected ? CONNECTED : DISCONNECTED); gtk_action_set_label (oper, is_connected ? _("Disconnect") : _("Connect")); } } g_free (name); if (oper != NULL) { g_object_set_data_full (G_OBJECT (oper), "connected", GINT_TO_POINTER (is_connected ? CONNECTED : DISCONNECTED), NULL); g_object_set_data_full (G_OBJECT (oper), "device-path", g_strdup (dbus_g_proxy_get_path (proxy)), g_free); } /* And now for the trick of the day */ if (is_connected != FALSE) { char *path; path = g_strdup_printf ("/bluetooth-applet-popup/devices-placeholder/%s", address); action_set_bold (uimanager, action, path); g_free (path); } num_devices++; if (proxy != NULL) g_object_unref (proxy); if (services != NULL) g_hash_table_unref (services); g_strfreev (uuids); g_free (alias); g_free (address); cont = gtk_tree_model_iter_next (devices_model, &iter); } /* Remove the left-over devices */ g_list_foreach (actions, (GFunc) remove_action_item, uimanager); g_list_free (actions); done: gtk_ui_manager_ensure_update (uimanager); gtk_action_set_visible (GTK_ACTION (gtk_builder_get_object (xml, "devices-label")), num_devices > 0); }