diff options
Diffstat (limited to 'src/indicator-bluetooth.vala')
-rw-r--r-- | src/indicator-bluetooth.vala | 283 |
1 files changed, 172 insertions, 111 deletions
diff --git a/src/indicator-bluetooth.vala b/src/indicator-bluetooth.vala index 88cb175..a157ab1 100644 --- a/src/indicator-bluetooth.vala +++ b/src/indicator-bluetooth.vala @@ -1,137 +1,198 @@ -[DBus (name = "org.bluez.Manager")] -interface BluezManager : Object +/* + * Copyright (C) 2012 Canonical Ltd. + * Author: Robert Ancell <robert.ancell@canonical.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 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +public class BluetoothIndicator : AppIndicator.Indicator { - public abstract string default_adapter () throws IOError; -} + private RFKillManager rfkill; + private Gtk.MenuItem status_item; + private Gtk.MenuItem enable_item; + private bool enable_value = false; + private Gtk.CheckMenuItem visible_item; + private Gtk.SeparatorMenuItem devices_separator; + private Gtk.MenuItem devices_item; + private List<Gtk.MenuItem> device_items; + private Gtk.MenuItem settings_item; + + public BluetoothIndicator () + { + Object (id: "indicator-bluetooth", icon_name: "bluetooth-active", category: "Hardware"); + + /* Monitor killswitch status */ + rfkill = new RFKillManager (); + rfkill.open (); + rfkill.device_added.connect (update_rfkill); + rfkill.device_changed.connect (update_rfkill); + rfkill.device_deleted.connect (update_rfkill); + + /* Get/control bluetooth status from Bluez */ + BluezAdapter adapter = null; + try + { + var manager = Bus.get_proxy_sync<BluezManager> (BusType.SYSTEM, "org.bluez", "/"); + var path = manager.default_adapter (); + adapter = Bus.get_proxy_sync<BluezAdapter> (BusType.SYSTEM, "org.bluez", path); + } + catch (IOError e) + { + stderr.printf ("Failed to connect to Bluez: %s", e.message); + } -[DBus (name = "org.bluez.Adapter")] -interface BluezAdapter : Object -{ - public abstract string[] list_devices () throws IOError; - public abstract HashTable<string, Variant> get_properties () throws IOError; - public abstract void set_property (string name, Variant value) throws IOError; -} + set_status (AppIndicator.IndicatorStatus.ACTIVE); -[DBus (name = "org.bluez.Device")] -interface BluezDevice : Object -{ - public abstract HashTable<string, Variant> get_properties () throws IOError; -} + var menu = new Gtk.Menu (); + set_menu (menu); -[DBus (name = "org.bluez.Audio")] -interface BluezAudio : Object -{ - public abstract void connect () throws IOError; -} + status_item = new Gtk.MenuItem (); + status_item.sensitive = false; + status_item.visible = true; + menu.append (status_item); -[DBus (name = "org.bluez.Input")] -interface BluezInput : Object -{ - public abstract void connect () throws IOError; -} + enable_item = new Gtk.MenuItem (); + enable_item.activate.connect (toggle_enabled); + menu.append (enable_item); -int main (string[] args) -{ - Intl.setlocale (LocaleCategory.ALL, ""); - Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); - Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - Intl.textdomain (GETTEXT_PACKAGE); + visible_item = new Gtk.CheckMenuItem.with_label (_("Visible")); + visible_item.activate.connect (() => { adapter.set_property ("Discoverable", new Variant.boolean (true)); }); // FIXME: Make rw + menu.append (visible_item); + + devices_separator = new Gtk.SeparatorMenuItem (); + menu.append (devices_separator); - Gtk.init (ref args); + devices_item = new Gtk.MenuItem.with_label (_("Devices")); + devices_item.sensitive = false; + devices_item.visible = true; + menu.append (devices_item); - BluezAdapter adapter; - try - { - var manager = Bus.get_proxy_sync<BluezManager> (BusType.SYSTEM, "org.bluez", "/"); - var path = manager.default_adapter (); - adapter = Bus.get_proxy_sync<BluezAdapter> (BusType.SYSTEM, "org.bluez", path); - } - catch (IOError e) - { - return Posix.EXIT_FAILURE; - } + device_items = new List<Gtk.MenuItem> (); - var indicator = new AppIndicator.Indicator ("indicator-bluetooth", "bluetooth-active", AppIndicator.IndicatorCategory.HARDWARE); - indicator.set_status (AppIndicator.IndicatorStatus.ACTIVE); + try + { + var devices = adapter.list_devices (); + foreach (var path in devices) + { + var device = Bus.get_proxy_sync<BluezDevice> (BusType.SYSTEM, "org.bluez", path); + var properties = device.get_properties (); + var iter = HashTableIter<string, Variant> (properties); + string name; + Variant value; + //stderr.printf ("%s\n", path); + while (iter.next (out name, out value)) + { + //stderr.printf (" %s=%s\n", name, value.print (false)); + if (name == "Name" && value.is_of_type (VariantType.STRING)) + { + var item = new Gtk.MenuItem.with_label (value.get_string ()); + device_items.append (item); + menu.append (item); + + item.submenu = new Gtk.Menu (); + var i = new Gtk.MenuItem.with_label (_("Send files...")); + i.visible = true; + i.activate.connect (() => { Process.spawn_command_line_async ("bluetooth-sendto --device=DEVICE --name=NAME"); }); + item.submenu.append (i); + + //var i = new Gtk.MenuItem.with_label (_("Keyboard Settings...")); + //i.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center keyboard"); }); + //var i = new Gtk.MenuItem.with_label (_("Mouse and Touchpad Settings...")); + //i.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center mouse"); }); + //var i = new Gtk.MenuItem.with_label (_("Sound Settings...")); + //i.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center sound"); }); + } + } + } + } + catch (IOError e) + { + stderr.printf ("%s\n", e.message); + } - var menu = new Gtk.Menu (); - indicator.set_menu (menu); + var sep = new Gtk.SeparatorMenuItem (); + sep.visible = true; + menu.append (sep); - var item = new Gtk.MenuItem.with_label ("Bluetooth: On"); - item.sensitive = false; - item.show (); - menu.append (item); + settings_item = new Gtk.MenuItem.with_label (_("Bluetooth Settings...")); + settings_item.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center bluetooth"); }); + settings_item.visible = true; + menu.append (settings_item); - item = new Gtk.MenuItem.with_label ("Turn off Bluetooth"); - item.show (); - menu.append (item); + update_rfkill (); + } - item = new Gtk.CheckMenuItem.with_label (_("Visible")); - item.activate.connect (() => { adapter.set_property ("Discoverable", new Variant.boolean (true)); }); - item.show (); - menu.append (item); - - var sep = new Gtk.SeparatorMenuItem (); - sep.show (); - menu.append (sep); + private void update_rfkill () + { + var have_lock = false; + var software_locked = false; + var hardware_locked = false; - item = new Gtk.MenuItem.with_label (_("Devices")); - item.sensitive = false; - item.show (); - menu.append (item); + foreach (var device in rfkill.get_devices ()) + { + if (device.device_type != RFKillDeviceType.BLUETOOTH) + continue; + + have_lock = true; + if (device.software_lock) + software_locked = true; + if (device.hardware_lock) + hardware_locked = true; + } + var locked = hardware_locked || software_locked; - try - { - var devices = adapter.list_devices (); - foreach (var path in devices) + if (hardware_locked) { - var device = Bus.get_proxy_sync<BluezDevice> (BusType.SYSTEM, "org.bluez", path); - var properties = device.get_properties (); - var iter = HashTableIter<string, Variant> (properties); - string name; - Variant value; - //stderr.printf ("%s\n", path); - while (iter.next (out name, out value)) - { - //stderr.printf (" %s=%s\n", name, value.print (false)); - if (name == "Name" && value.is_of_type (VariantType.STRING)) - { - item = new Gtk.MenuItem.with_label (value.get_string ()); - item.show (); - menu.append (item); - - item.submenu = new Gtk.Menu (); - var i = new Gtk.MenuItem.with_label (_("Send files...")); - i.show (); - i.activate.connect (() => { Process.spawn_command_line_async ("bluetooth-sendto --device=DEVICE --name=NAME"); }); - item.submenu.append (i); - - //var i = new Gtk.MenuItem.with_label (_("Keyboard Settings...")); - //i.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center keyboard"); }); - //var i = new Gtk.MenuItem.with_label (_("Mouse and Touchpad Settings...")); - //i.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center mouse"); }); - //var i = new Gtk.MenuItem.with_label (_("Sound Settings...")); - //i.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center sound"); }); - } - } + status_item.label = _("Bluetooth: Disabled"); + enable_item.visible = false; } + else if (software_locked) + { + status_item.label = _("Bluetooth: Off"); + enable_item.label = _("Turn on Bluetooth"); + enable_item.visible = true; + enable_value = false; + } + else + { + status_item.label = _("Bluetooth: On"); + enable_item.label = _("Turn off Bluetooth"); + enable_item.visible = true; + enable_value = true; + } + + /* Disable devices when locked */ + visible_item.visible = !locked; + devices_separator.visible = !locked; + devices_item.visible = !locked; + foreach (var item in device_items) + item.visible = !locked; } - catch (IOError e) + + private void toggle_enabled () { - stderr.printf ("%s\n", e.message); - return Posix.EXIT_FAILURE; + rfkill.set_software_lock (RFKillDeviceType.BLUETOOTH, enable_value); } +} - sep = new Gtk.SeparatorMenuItem (); - sep.show (); - menu.append (sep); +public static int main (string[] args) +{ + Intl.setlocale (LocaleCategory.ALL, ""); + Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); + Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + Intl.textdomain (GETTEXT_PACKAGE); - item = new Gtk.MenuItem.with_label (_("Bluetooth Settings...")); - item.activate.connect (() => { Process.spawn_command_line_async ("gnome-control-center bluetooth"); }); - item.show (); - menu.append (item); + Gtk.init (ref args); + var indicator = new BluetoothIndicator (); + Gtk.main (); + + indicator = null; - return 0; + return Posix.EXIT_SUCCESS; } |