diff options
author | Charles Kerr <charles.kerr@canonical.com> | 2013-08-01 01:34:47 -0500 |
---|---|---|
committer | Charles Kerr <charles.kerr@canonical.com> | 2013-08-01 01:34:47 -0500 |
commit | 3cc732f558737acd0004efb013993515845e67d7 (patch) | |
tree | cc554df46298fb7d01130f71024e55017b4bc007 /src | |
parent | 39263df5ab76e2f444e5dbb702512f741c56830c (diff) | |
download | ayatana-indicator-bluetooth-3cc732f558737acd0004efb013993515845e67d7.tar.gz ayatana-indicator-bluetooth-3cc732f558737acd0004efb013993515845e67d7.tar.bz2 ayatana-indicator-bluetooth-3cc732f558737acd0004efb013993515845e67d7.zip |
add per-profile icons and initial menus w/settings section
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 34 | ||||
-rw-r--r-- | src/desktop.vala | 99 | ||||
-rw-r--r-- | src/gnome-bluetooth-1.0.vapi | 82 | ||||
-rw-r--r-- | src/indicator-bluetooth.vala | 142 | ||||
-rw-r--r-- | src/main.vala | 17 | ||||
-rw-r--r-- | src/menu.vala | 53 | ||||
-rw-r--r-- | src/phone.vala | 76 | ||||
-rw-r--r-- | src/service.vala (renamed from src/indicator-bluetooth-service.vala) | 75 |
8 files changed, 300 insertions, 278 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 2b92f9b..ed2c976 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,17 +1,18 @@ pkglibexec_PROGRAMS = indicator-bluetooth-service -indicatordir = ${libdir}/indicators3/7 -indicator_LTLIBRARIES = libbluetooth.la indicator_bluetooth_service_SOURCES = \ indicator3-0.4.vapi \ - gnome-bluetooth-1.0.vapi \ + desktop.vala \ main.vala \ - indicator-bluetooth-service.vala + menu.vala \ + phone.vala \ + service.vala indicator_bluetooth_service_VALAFLAGS = \ --ccode \ --vapidir=$(top_srcdir)/vapi/ \ --vapidir=./ \ + --pkg gnome-bluetooth-1.0 \ --pkg config \ --pkg posix \ --pkg glib-2.0 \ @@ -26,31 +27,6 @@ indicator_bluetooth_service_CFLAGS = \ indicator_bluetooth_service_LDADD = \ $(INDICATOR_BLUETOOTH_SERVICE_LIBS) -libbluetooth_la_SOURCES = \ - indicator3-0.4.vapi \ - indicator-bluetooth.vala \ - libido3-0.1.vapi - -libbluetooth_la_VALAFLAGS = \ - --ccode \ - --vapidir=$(top_srcdir)/vapi/ \ - --vapidir=./ \ - --pkg posix \ - --pkg glib-2.0 \ - --pkg gtk+-3.0 \ - --pkg Dbusmenu-0.4 \ - --pkg DbusmenuGtk3-0.4 - -libbluetooth_la_CFLAGS = \ - -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ - $(INDICATOR_BLUETOOTH_CFLAGS) - -libbluetooth_la_LIBADD = \ - $(INDICATOR_BLUETOOTH_LIBS) - -libbluetooth_la_LDFLAGS = \ - -module -avoid-version - CLEANFILES = \ $(patsubst %.vala,%.c,$(filter %.vala, $(SOURCES))) \ *_vala.stamp diff --git a/src/desktop.vala b/src/desktop.vala new file mode 100644 index 0000000..bd005f5 --- /dev/null +++ b/src/desktop.vala @@ -0,0 +1,99 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * 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; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +class DesktopMenu: BluetoothMenu +{ + private Settings settings; + + private Action[] actions; + + public override void add_actions_to_group (SimpleActionGroup group) + { + base.add_actions_to_group (group); + + for (var i=0; i<this.actions.length; i++) + group.insert (actions[i]); + } + + public DesktopMenu () + { + base ("desktop"); + + this.settings = new Settings ("com.canonical.indicator.bluetooth"); + this.settings.changed["visible"].connect (()=> { message("visible toggled"); }); + + this.actions = {}; + this.actions += new SimpleAction.stateful ("root-desktop", null, action_state_for_root()); + this.actions += create_settings_action (); + this.actions += create_wizard_action (); + + var section = new Menu (); + section.append (_("Set Up New Device…"), "indicator.desktop-wizard"); + section.append (_("Bluetooth Settings…"), "indicator.desktop-settings"); + this.menu.append_section (null, section); + } + + Action create_wizard_action () + { + var action = new SimpleAction ("desktop-wizard", null); + + action.activate.connect ((action, param) => { + try { + Process.spawn_command_line_async ("bluetooth-wizard"); + } catch (Error e) { + warning ("unable to launch settings: %s", e.message); + } + }); + + return action; + } + + Action create_settings_action () + { + var action = new SimpleAction ("desktop-settings", null); + + action.activate.connect ((action, param) => { + try { + Process.spawn_command_line_async ("gnome-control-center bluetooth"); + } catch (Error e) { + warning ("unable to launch settings: %s", e.message); + } + }); + + return action; + } + + protected Variant action_state_for_root () + { + var label = "Hello"; // FIXME + var a11y = "Hello"; // FIXME + var visible = true; // FIXME + + string icon_name = "bluetooth-active"; // FIXME: enabled, disabled, connected, etc. +//indicator-bluetooth-service.vala: bluetooth_service._icon_name = enabled ? "bluetooth-active" : "bluetooth-disabled"; + var icon = new ThemedIcon.with_default_fallbacks (icon_name); + + var builder = new VariantBuilder (new VariantType ("a{sv}")); + builder.add ("{sv}", "visible", new Variant ("b", visible)); + builder.add ("{sv}", "label", new Variant ("s", label)); + builder.add ("{sv}", "accessible-desc", new Variant ("s", a11y)); + builder.add ("{sv}", "icon", icon.serialize()); + return builder.end (); + } +} diff --git a/src/gnome-bluetooth-1.0.vapi b/src/gnome-bluetooth-1.0.vapi deleted file mode 100644 index 6d6aa09..0000000 --- a/src/gnome-bluetooth-1.0.vapi +++ /dev/null @@ -1,82 +0,0 @@ -[CCode (cprefix = "Bluetooth", lower_case_cprefix = "bluetooth_")] -namespace GnomeBluetooth -{ - -[CCode (cheader_filename = "bluetooth-client.h")] -public class Client : GLib.Object -{ - public Client (); - public Gtk.TreeModel model { get; } - public Gtk.TreeModel adapter_model { get; } - public Gtk.TreeModel device_model { get; } - [CCode (finish_function = "bluetooth_client_connect_service_finish")] - public async bool connect_service (string device, bool connect, GLib.Cancellable? cancellable = null) throws GLib.Error; -} - -[CCode (cheader_filename = "bluetooth-enums.h", cprefix = "BLUETOOTH_COLUMN_")] -public enum Column -{ - PROXY, - ADDRESS, - ALIAS, - NAME, - TYPE, - ICON, - DEFAULT, - PAIRED, - TRUSTED, - CONNECTED, - DISCOVERABLE, - DISCOVERING, - LEGACYPAIRING, - POWERED, - SERVICES, - UUIDS -} - -[CCode (cheader_filename = "bluetooth-enums.h", cprefix = "BLUETOOTH_TYPE_")] -public enum Type -{ - ANY, - PHONE, - MODEM, - COMPUTER, - NETWORK, - HEADSET, - HEADPHONES, - OTHER_AUDIO, - KEYBOARD, - MOUSE, - CAMERA, - PRINTER, - JOYPAD, - TABLET, - VIDEO -} - -[CCode (cheader_filename = "bluetooth-utils.h")] -public void browse_address (GLib.Object? object, string address, uint timestamp, GLib.AsyncReadyCallback? callback); - -[CCode (cheader_filename = "bluetooth-utils.h")] -public void send_to_address (string address, string alias); - -[CCode (cheader_filename = "bluetooth-killswitch.h", cprefix = "BLUETOOTH_KILLSWITCH_STATE_")] -public enum KillswitchState -{ - NO_ADAPTER, - SOFT_BLOCKED, - UNBLOCKED, - HARD_BLOCKED -} - -[CCode (cheader_filename = "bluetooth-killswitch.h")] -public class Killswitch : GLib.Object -{ - public Killswitch (); - public signal void state_changed (KillswitchState state); - public bool has_killswitches (); - public KillswitchState state { get; set; } - public unowned string state_to_string (); -} - -} diff --git a/src/indicator-bluetooth.vala b/src/indicator-bluetooth.vala deleted file mode 100644 index bfbbc9f..0000000 --- a/src/indicator-bluetooth.vala +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2012-2013 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, version 3 of the License. - * See http://www.gnu.org/copyleft/gpl.html the full text of the license. - */ - -public class BluetoothIndicator : Indicator.Object -{ - private Indicator.ServiceManager service; - private Gtk.Image image; - private DbusmenuGtk.Menu menu; - private BluetoothService proxy; - private string accessible_description = _("Bluetooth: On"); - - construct - { - service = new Indicator.ServiceManager ("com.canonical.indicator.bluetooth"); - service.connection_change.connect (connection_change_cb); - menu = new DbusmenuGtk.Menu ("com.canonical.indicator.bluetooth", "/com/canonical/indicator/bluetooth/menu"); - image = Indicator.image_helper ("bluetooth-active"); - image.visible = true; - - var menu_client = menu.get_client (); - menu_client.add_type_handler_full ("x-canonical-switch", new_switch_cb); - - /* Hide until ready */ - set_visible (false); - } - - private bool new_switch_cb (Dbusmenu.Menuitem newitem, Dbusmenu.Menuitem parent, Dbusmenu.Client client) - { - var item = new Switch (newitem); - (client as DbusmenuGtk.Client).newitem_base (newitem, item, parent); - return true; - } - - public override unowned Gtk.Image get_image () - { - return image; - } - - public override unowned Gtk.Menu get_menu () - { - return menu; - } - - public override unowned string get_accessible_desc () - { - return accessible_description; - } - - private void connection_change_cb (bool connected) - { - if (!connected) - return; - - // FIXME: Set proxy to null on disconnect? - // FIXME: Use Cancellable to cancel existing connection - if (proxy == null) - { - Bus.get_proxy.begin<BluetoothService> (BusType.SESSION, - "com.canonical.indicator.bluetooth", - "/com/canonical/indicator/bluetooth/service", - DBusProxyFlags.NONE, null, (object, result) => - { - try - { - proxy = Bus.get_proxy.end (result); - proxy.g_properties_changed.connect (server_properties_changed_cb); - server_properties_changed_cb (); - } - catch (IOError e) - { - warning ("Failed to connect to bluetooth service: %s", e.message); - } - }); - } - } - - private void server_properties_changed_cb () - { - set_visible (proxy.visible); - Indicator.image_helper_update (image, proxy.icon_name); - accessible_description = proxy.accessible_description; - } -} - -public class Switch : Ido.SwitchMenuItem -{ - public Dbusmenu.Menuitem menuitem; - public new Gtk.Label label; - private bool updating_switch = false; - - public Switch (Dbusmenu.Menuitem menuitem) - { - this.menuitem = menuitem; - label = new Gtk.Label (""); - label.visible = true; - content_area.add (label); - - /* Be the first listener to the activate signal so we can stop it - * emitting when we change the state. Without this you get feedback loops */ - activate.connect (() => - { - if (updating_switch) - Signal.stop_emission_by_name (this, "activate"); - }); - - menuitem.property_changed.connect ((mi, prop, value) => { update (); }); - update (); - } - - private void update () - { - updating_switch = true; - label.label = menuitem.property_get (Dbusmenu.MENUITEM_PROP_LABEL); - active = menuitem.property_get_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE) == Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED; - updating_switch = false; - } -} - -[DBus (name = "com.canonical.indicator.bluetooth.service")] -public interface BluetoothService : DBusProxy -{ - public abstract bool visible { owned get; } - public abstract string icon_name { owned get; } - public abstract string accessible_description { owned get; } -} - -public static string get_version () -{ - return Indicator.VERSION; -} - -public static GLib.Type get_type () -{ - return typeof (BluetoothIndicator); -} diff --git a/src/main.vala b/src/main.vala index 79683b2..1df55c3 100644 --- a/src/main.vala +++ b/src/main.vala @@ -7,21 +7,8 @@ main (string[] args) Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.GNOMELOCALEDIR); Intl.textdomain (Config.GETTEXT_PACKAGE); - var loop = new MainLoop (); + var service = new BluetoothIndicator (); + service.run (); - BluetoothIndicator indicator; - try - { - indicator = new BluetoothIndicator (); - } - catch (Error e) - { - warning ("Failed to start bluetooth indicator service: %s", e.message); - return Posix.EXIT_FAILURE; - } - - loop.run (); return Posix.EXIT_SUCCESS; } - //var service = new IndicatorSound.Service (); - //return service.run (); diff --git a/src/menu.vala b/src/menu.vala new file mode 100644 index 0000000..a2c5449 --- /dev/null +++ b/src/menu.vala @@ -0,0 +1,53 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * 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; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +class BluetoothMenu: Object +{ + protected Menu root; + protected Menu menu; + + public virtual void add_actions_to_group (SimpleActionGroup group) + { + } + + public BluetoothMenu (string profile) + { + this.menu = new Menu (); + + var root_item = new MenuItem (null, "indicator.root-" + profile); + root_item.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.root"); + root_item.set_submenu (this.menu); + + this.root = new Menu (); + this.root.append_item (root_item); + } + + public void export (DBusConnection connection, string object_path) + { + try + { + message ("exporting on %s", object_path); + connection.export_menu_model (object_path, this.root); + } + catch (Error e) + { + critical ("%s", e.message); + } + } +} diff --git a/src/phone.vala b/src/phone.vala new file mode 100644 index 0000000..2abcf11 --- /dev/null +++ b/src/phone.vala @@ -0,0 +1,76 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * 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; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +class PhoneMenu: BluetoothMenu +{ + private Action[] actions; + + public override void add_actions_to_group (SimpleActionGroup group) + { + base.add_actions_to_group (group); + + for (var i=0; i<actions.length; i++) + group.insert (actions[i]); + } + + public PhoneMenu () + { + base ("phone"); + + this.actions = {}; + this.actions += new SimpleAction.stateful ("root-phone", null, action_state_for_root()); + this.actions += create_settings_action (); + + var section = new Menu (); + section.append (_("Sound settings…"), "indicator.phone-settings"); + this.menu.append_section (null, section); + } + + Action create_settings_action () + { + var action = new SimpleAction ("phone-settings", null); + + action.activate.connect ((action, param) => { + try { + Process.spawn_command_line_async ("system-settings bluetooth"); + } catch (Error e) { + warning ("unable to launch settings: %s", e.message); + } + }); + + return action; + } + + protected Variant action_state_for_root () + { + var label = "Hello World"; // FIXME + var a11y = "Hello World"; // FIXME + var visible = true; // FIXME + + string icon_name = "bluetooth"; // FIXME: enabled, disabled, connected, etc. + var icon = new ThemedIcon.with_default_fallbacks (icon_name); + + var builder = new VariantBuilder (new VariantType ("a{sv}")); + builder.add ("{sv}", "visible", new Variant ("b", visible)); + builder.add ("{sv}", "label", new Variant ("s", label)); + builder.add ("{sv}", "accessible-desc", new Variant ("s", a11y)); + builder.add ("{sv}", "icon", icon.serialize()); + return builder.end (); + } +} diff --git a/src/indicator-bluetooth-service.vala b/src/service.vala index f65c538..b6ae0f3 100644 --- a/src/indicator-bluetooth-service.vala +++ b/src/service.vala @@ -10,7 +10,10 @@ public class BluetoothIndicator { - private Settings settings; + private MainLoop loop; + private SimpleActionGroup actions; + private HashTable<string, BluetoothMenu> menus; + private DBusConnection bus; private Indicator.Service indicator_service; private Dbusmenu.Server menu_server; @@ -27,16 +30,23 @@ public class BluetoothIndicator public BluetoothIndicator () throws Error { - settings = new Settings ("com.canonical.indicator.bluetooth"); - settings.changed.connect ((key) => - { - if (key == "visible") - update_visible (); - }); + var phone = new PhoneMenu (); + var desktop = new DesktopMenu (); + + this.menus = new HashTable<string, BluetoothMenu> (str_hash, str_equal); + this.menus.insert ("phone", phone); + this.menus.insert ("desktop", desktop); - bus = Bus.get_sync (BusType.SESSION); + this.actions = new SimpleActionGroup (); + phone.add_actions_to_group (this.actions); + desktop.add_actions_to_group (this.actions); + } + + private void init_for_bus (DBusConnection bus) + { + this.bus = bus; - indicator_service = new Indicator.Service ("com.canonical.indicator.bluetooth"); + indicator_service = new Indicator.Service ("com.canonical.indicator.bluetooth.old"); menu_server = new Dbusmenu.Server ("/com/canonical/indicator/bluetooth/menu"); bluetooth_service = new BluetoothService (); @@ -130,6 +140,51 @@ public class BluetoothIndicator update_visible (); } + public int run () + { + if (this.loop != null) + { + warning ("service is already running"); + return 1; + } + + Bus.own_name (BusType.SESSION, + "com.canonical.indicator.bluetooth", + BusNameOwnerFlags.NONE, + this.on_bus_acquired, + null, + this.on_name_lost); + + this.loop = new MainLoop (null, false); + this.loop.run (); + return 0; + } + + void on_bus_acquired (DBusConnection connection, string name) + { + stdout.printf ("bus acquired: %s\n", name); + + init_for_bus (connection); + + try + { + connection.export_action_group ("/com/canonical/indicator/bluetooth", this.actions); + } + catch (Error e) + { + critical ("%s", e.message); + } + + this.menus.@foreach ( (profile, menu) => menu.export (connection, @"/com/canonical/indicator/bluetooth/$profile")); + } + + void on_name_lost (DBusConnection connection, string name) + { + stdout.printf ("name lost: %s\n", name); + this.loop.quit (); + } + + private BluetoothMenuItem? find_menu_item (string address) { foreach (var item in device_items) @@ -186,7 +241,7 @@ public class BluetoothIndicator private void update_visible () { - bluetooth_service._visible = client.adapter_model.iter_n_children (null) > 0 && settings.get_boolean ("visible"); + bluetooth_service._visible = client.adapter_model.iter_n_children (null) > 0;// && settings.get_boolean ("visible"); var builder = new VariantBuilder (VariantType.ARRAY); builder.add ("{sv}", "Visible", new Variant.boolean (bluetooth_service._visible)); try |