aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCharles Kerr <charles.kerr@canonical.com>2013-08-01 01:34:47 -0500
committerCharles Kerr <charles.kerr@canonical.com>2013-08-01 01:34:47 -0500
commit3cc732f558737acd0004efb013993515845e67d7 (patch)
treecc554df46298fb7d01130f71024e55017b4bc007 /src
parent39263df5ab76e2f444e5dbb702512f741c56830c (diff)
downloadayatana-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.am34
-rw-r--r--src/desktop.vala99
-rw-r--r--src/gnome-bluetooth-1.0.vapi82
-rw-r--r--src/indicator-bluetooth.vala142
-rw-r--r--src/main.vala17
-rw-r--r--src/menu.vala53
-rw-r--r--src/phone.vala76
-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