aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Kerr <charles.kerr@canonical.com>2013-08-01 18:21:05 -0500
committerCharles Kerr <charles.kerr@canonical.com>2013-08-01 18:21:05 -0500
commitcf894302767d5ec483b5f8002bb796a284895bbf (patch)
treedb2db117dd355db27e72efa9087b8e18a43d38ae
parent3cc732f558737acd0004efb013993515845e67d7 (diff)
downloadayatana-indicator-bluetooth-cf894302767d5ec483b5f8002bb796a284895bbf.tar.gz
ayatana-indicator-bluetooth-cf894302767d5ec483b5f8002bb796a284895bbf.tar.bz2
ayatana-indicator-bluetooth-cf894302767d5ec483b5f8002bb796a284895bbf.zip
add a bluetooth backend to track bluetooth being enabled, being hard/soft blocked, and its devices.
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac8
-rw-r--r--data/Makefile.am2
-rw-r--r--debian/control2
-rw-r--r--src/Makefile.am5
-rw-r--r--src/bluetooth.vala53
-rw-r--r--src/bluez.vala97
-rw-r--r--src/desktop.vala121
-rw-r--r--src/killswitch.vala147
-rw-r--r--src/libido3-0.1.vapi10
-rw-r--r--src/main.vala4
-rw-r--r--src/org-bluez.vala293
-rw-r--r--src/phone.vala2
-rw-r--r--src/service.vala21
-rw-r--r--vapi/rfkill.vapi44
15 files changed, 748 insertions, 67 deletions
diff --git a/Makefile.am b/Makefile.am
index 4fa38ad..31ba5e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,9 @@
SUBDIRS = data po src
-EXTRA_DIST = autogen.sh NEWS
+EXTRA_DIST = \
+ autogen.sh \
+ NEWS \
+ vapi/rfkill.vapi \
+ vapi/config.vapi
DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall
diff --git a/configure.ac b/configure.ac
index 3179a1e..15f09ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,14 +21,6 @@ PKG_CHECK_MODULES(INDICATOR_BLUETOOTH_SERVICE, [
dbusmenu-gtk3-0.4
])
-PKG_CHECK_MODULES(INDICATOR_BLUETOOTH, [
- glib-2.0
- gtk+-3.0
- indicator3-0.4
- dbusmenu-gtk3-0.4
- libido3-0.1
-])
-
dnl ##############################
dnl # Custom Junk
dnl ##############################
diff --git a/data/Makefile.am b/data/Makefile.am
index d5f40aa..fc726a7 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1,7 +1,7 @@
# the indicator bus file
indicatorsdir = $(prefix)/share/unity/indicators
-dist_indicators_DATA = com.canonical.indicator.datetime
+dist_indicators_DATA = com.canonical.indicator.bluetooth
# the dbus service file
dbus_servicesdir = $(datadir)/dbus-1/services
diff --git a/debian/control b/debian/control
index 07bc74d..a08015d 100644
--- a/debian/control
+++ b/debian/control
@@ -8,9 +8,7 @@ Build-Depends: debhelper (>= 9.0),
gnome-common,
libdbusmenu-gtk3-dev,
libglib2.0-dev,
- libgnome-bluetooth-dev,
libgtk-3-dev,
- libido3-0.1-dev,
libindicator3-dev,
valac (>=0.18),
Standards-Version: 3.9.4
diff --git a/src/Makefile.am b/src/Makefile.am
index ed2c976..720c981 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,10 +2,14 @@ pkglibexec_PROGRAMS = indicator-bluetooth-service
indicator_bluetooth_service_SOURCES = \
indicator3-0.4.vapi \
+ org-bluez.vala \
+ bluetooth.vala \
+ bluez.vala \
desktop.vala \
main.vala \
menu.vala \
phone.vala \
+ killswitch.vala \
service.vala
indicator_bluetooth_service_VALAFLAGS = \
@@ -14,6 +18,7 @@ indicator_bluetooth_service_VALAFLAGS = \
--vapidir=./ \
--pkg gnome-bluetooth-1.0 \
--pkg config \
+ --pkg rfkill \
--pkg posix \
--pkg glib-2.0 \
--pkg gtk+-3.0 \
diff --git a/src/bluetooth.vala b/src/bluetooth.vala
new file mode 100644
index 0000000..ad5ee09
--- /dev/null
+++ b/src/bluetooth.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>
+ */
+
+public class Bluetooth: Object
+{
+ /***
+ **** Properties
+ ***/
+
+ public bool discoverable { get; protected set; default = false; }
+ public virtual void try_set_discoverable (bool b) {}
+
+ public bool powered { get; protected set; default = false; }
+
+ public bool blocked { get; protected set; default = true; }
+ public virtual void try_set_blocked (bool b) {
+ kill_switch.try_set_blocked (b);
+ }
+
+ /***
+ **** Killswitch Implementation
+ ***/
+
+ protected KillSwitch kill_switch;
+
+ public Bluetooth (KillSwitch kill_switch)
+ {
+ this.kill_switch = kill_switch;
+
+ message ("changing blocked to %d", (int)!this.kill_switch.blocked);
+ blocked = this.kill_switch.blocked;
+ kill_switch.notify["blocked"].connect (() => {
+ message ("bluetooth changing blocked to %d", (int)kill_switch.blocked);
+ this.blocked = kill_switch.blocked;
+ });
+ }
+}
diff --git a/src/bluez.vala b/src/bluez.vala
new file mode 100644
index 0000000..178cc57
--- /dev/null
+++ b/src/bluez.vala
@@ -0,0 +1,97 @@
+/*
+ * 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>
+ */
+
+public class Bluez: Bluetooth
+{
+ private org.bluez.Manager manager;
+ private org.bluez.Adapter default_adapter;
+
+ public Bluez (KillSwitch kill_switch)
+ {
+ string default_adapter_object_path = null;
+
+ base (kill_switch);
+
+ try
+ {
+ manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", "/");
+
+ manager.default_adapter_changed.connect ((object_path) => on_default_adapter_changed (object_path));
+ default_adapter_object_path = manager.default_adapter ();
+ }
+ catch (Error e)
+ {
+ critical ("%s", e.message);
+ }
+
+ on_default_adapter_changed (default_adapter_object_path);
+ }
+
+ private void on_default_adapter_changed (string? object_path)
+ {
+ if (object_path != null) try
+ {
+ message ("using default adapter at %s", object_path);
+ this.default_adapter = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", object_path);
+ this.default_adapter.property_changed.connect(() => this.on_default_adapter_properties_changed());
+ }
+ catch (Error e)
+ {
+ critical ("%s", e.message);
+ }
+
+ this.on_default_adapter_properties_changed ();
+ }
+
+ private void on_default_adapter_properties_changed ()
+ {
+ bool is_discoverable = false;
+ bool is_powered = false;
+
+ if (this.default_adapter != null) try
+ {
+ var properties = this.default_adapter.get_properties();
+
+ var v = properties.lookup("Discoverable");
+ is_discoverable = (v != null) && v.get_boolean ();
+
+ v = properties.lookup("Powered");
+ is_powered = (v != null) && v.get_boolean ();
+ }
+ catch (Error e)
+ {
+ critical ("%s", e.message);
+ }
+
+ this.powered = is_powered;
+ this.discoverable = is_discoverable;
+ }
+
+ public override void try_set_discoverable (bool b)
+ {
+ if (discoverable != b) try
+ {
+ this.default_adapter.set_property ("Discoverable", new Variant.boolean(b));
+ }
+ catch (Error e)
+ {
+ critical ("%s", e.message);
+ }
+ }
+}
diff --git a/src/desktop.vala b/src/desktop.vala
index bd005f5..351770a 100644
--- a/src/desktop.vala
+++ b/src/desktop.vala
@@ -20,80 +20,133 @@
class DesktopMenu: BluetoothMenu
{
private Settings settings;
+ private Bluetooth bluetooth;
- private Action[] actions;
+ private SimpleAction root_action;
+ private Action[] all_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]);
+ for (var i=0; i<this.all_actions.length; i++)
+ group.insert (all_actions[i]);
}
- public DesktopMenu ()
+ public DesktopMenu (Bluetooth bluetooth)
{
base ("desktop");
+ this.bluetooth = bluetooth;
+
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 ();
+ this.root_action = new SimpleAction.stateful ("root-desktop", null, action_state_for_root());
+
+ this.all_actions = {};
+ this.all_actions += this.root_action;
+ this.all_actions += create_enabled_action (bluetooth);
+ this.all_actions += create_discoverable_action (bluetooth);
+ this.all_actions += create_settings_action ();
+ this.all_actions += create_wizard_action ();
+
+ bluetooth.notify.connect (() => this.update_root_action_state());
+ settings.changed["visible"].connect (()=> this.update_root_action_state());
+
+ Menu section;
+ MenuItem item;
- var section = new Menu ();
+ section = new Menu ();
+ item = new MenuItem ("Bluetooth", "indicator.desktop-enabled");
+ item.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.switch");
+ section.append_item (item);
+ item = new MenuItem ("Visible", "indicator.desktop-discoverable");
+ item.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.switch");
+ section.append_item (item);
+ this.menu.append_section (null, section);
+
+ 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 ()
+ Action create_enabled_action (Bluetooth bluetooth)
{
- var action = new SimpleAction ("desktop-wizard", null);
+ var action = new SimpleAction.stateful ("desktop-enabled", null, !bluetooth.blocked);
+ action.activate.connect (() => action.set_state (!action.get_state().get_boolean()));
+ action.notify["state"].connect (() => bluetooth.try_set_blocked (!action.get_state().get_boolean()));
+ bluetooth.notify["blocked"].connect (() => action.set_state (!bluetooth.blocked));
+ return action;
+ }
- action.activate.connect ((action, param) => {
- try {
- Process.spawn_command_line_async ("bluetooth-wizard");
- } catch (Error e) {
- warning ("unable to launch settings: %s", e.message);
- }
- });
+ Action create_discoverable_action (Bluetooth bluetooth)
+ {
+ var action = new SimpleAction.stateful ("desktop-discoverable", null, bluetooth.discoverable);
+ action.set_enabled (bluetooth.powered);
+ action.activate.connect (() => action.set_state (!action.get_state().get_boolean()));
+ action.notify["state"].connect (() => bluetooth.try_set_discoverable (action.get_state().get_boolean()));
+ bluetooth.notify["discoverable"].connect (() => action.set_state (bluetooth.discoverable));
+ bluetooth.notify["powered"].connect (() => action.set_enabled (bluetooth.powered));
+ return action;
+ }
+ void spawn_command_line_async (string command)
+ {
+ try {
+ Process.spawn_command_line_async (command);
+ } catch (Error e) {
+ warning ("unable to launch '%s': %s", command, e.message);
+ }
+ }
+
+ Action create_wizard_action ()
+ {
+ var action = new SimpleAction ("desktop-wizard", null);
+ action.activate.connect (() => spawn_command_line_async ("bluetooth-wizard"));
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);
- }
- });
-
+ action.activate.connect (() => spawn_command_line_async ("gnome-control-center bluetooth"));
return action;
}
protected Variant action_state_for_root ()
{
- var label = "Hello"; // FIXME
- var a11y = "Hello"; // FIXME
- var visible = true; // FIXME
+ bool blocked = bluetooth.blocked;
+ bool powered = bluetooth.powered;
+
+ settings.changed["visible"].connect (()=> this.update_root_action_state());
+
+ bool visible = powered && settings.get_boolean("visible");
+
+ string a11y;
+ string icon_name;
+ if (powered && !blocked)
+ {
+ a11y = "Bluetooth (on)";
+ icon_name = "bluetooth-active";
+ }
+ else
+ {
+ a11y = "Bluetooth (off)";
+ icon_name = "bluetooth-disabled";
+ }
- 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 ();
}
+
+ void update_root_action_state ()
+ {
+ root_action.set_state (action_state_for_root ());
+ }
}
diff --git a/src/killswitch.vala b/src/killswitch.vala
new file mode 100644
index 0000000..92b1a3c
--- /dev/null
+++ b/src/killswitch.vala
@@ -0,0 +1,147 @@
+/*
+ * 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>
+ */
+
+/**
+ * Monitors whether or not bluetooth is blocked,
+ * either by software (e.g., a session configuration setting)
+ * or by hardware (e.g., user disabled it via a physical switch on her laptop)
+ */
+public class KillSwitch: Object
+{
+ public bool blocked { get; protected set; default = false; }
+
+ public void try_set_blocked (bool blocked)
+ {
+ return_if_fail (this.blocked != blocked);
+
+ // write a 'soft kill' event to fkill
+ var event = Linux.RfKillEvent() {
+ op = Linux.RfKillOp.CHANGE_ALL,
+ type = Linux.RfKillType.BLUETOOTH,
+ soft = (uint8)blocked
+ };
+
+ var bwritten = Posix.write (fd, &event, sizeof(Linux.RfKillEvent));
+ if (bwritten == -1)
+ warning ("Could not write rfkill event: %s", strerror(errno));
+ }
+
+ /***
+ **** Past this point, it's all RfKill implementation details...
+ ***/
+
+ private class Entry
+ {
+ public uint32 idx;
+ public Linux.RfKillType type;
+ public bool soft;
+ public bool hard;
+ }
+
+ private HashTable<uint32,Entry> entries;
+ private int fd;
+ private IOChannel channel;
+ private uint watch;
+
+ private bool calculate_blocked ()
+ {
+ foreach (Entry entry in entries.get_values())
+ if (entry.soft || entry.hard)
+ return true;
+
+ return false;
+ }
+
+ ~KillSwitch ()
+ {
+ Source.remove (watch);
+ Posix.close (fd);
+ }
+
+ public KillSwitch ()
+ {
+ entries = new HashTable<uint32,Entry>(direct_hash, direct_equal);
+
+ var path = "/dev/rfkill";
+ fd = Posix.open (path, Posix.O_RDWR | Posix.O_NONBLOCK );
+ message ("fd is %d", fd);
+ if (fd == -1)
+ {
+ warning (@"Can't open $path: $(strerror(errno)); KillSwitch disable");
+ }
+ else
+ {
+ // read everything that's already there, then watch for more
+ while (read_event());
+ channel = new IOChannel.unix_new (fd);
+ watch = channel.add_watch (IOCondition.IN, on_channel_event);
+ }
+ }
+
+ private bool on_channel_event (IOChannel source, IOCondition condition)
+ {
+ read_event ();
+ return true;
+ }
+
+ private bool read_event ()
+ {
+ assert (fd != -1);
+
+ var event = Linux.RfKillEvent();
+ var n = sizeof (Linux.RfKillEvent);
+ var bytesread = Posix.read (fd, &event, n);
+
+ if (bytesread == n)
+ {
+ process_event (event);
+ return true;
+ }
+
+ return false;
+ }
+
+ private void process_event (Linux.RfKillEvent event)
+ {
+ // we only want things that affect bluetooth
+ if ((event.type != Linux.RfKillType.ALL) &&
+ (event.type != Linux.RfKillType.BLUETOOTH))
+ return;
+
+ switch (event.op)
+ {
+ case Linux.RfKillOp.CHANGE:
+ case Linux.RfKillOp.ADD:
+ Entry entry = new Entry ();
+ entry.idx = event.idx;
+ entry.type = event.type;
+ entry.soft = event.soft != 0;
+ entry.hard = event.hard != 0;
+ entries.insert (entry.idx, entry);
+ break;
+
+ case Linux.RfKillOp.DEL:
+ entries.remove (event.idx);
+ break;
+ }
+
+ // update the 'blocked' property
+ blocked = calculate_blocked ();
+ }
+}
diff --git a/src/libido3-0.1.vapi b/src/libido3-0.1.vapi
deleted file mode 100644
index e6a8953..0000000
--- a/src/libido3-0.1.vapi
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Ido
-{
- [CCode (cheader_filename = "libido/idoswitchmenuitem.h")]
- public class SwitchMenuItem : Gtk.CheckMenuItem
- {
- [CCode (has_construct_function = false)]
- public SwitchMenuItem ();
- public Gtk.Container content_area { get; }
- }
-}
diff --git a/src/main.vala b/src/main.vala
index 1df55c3..7af617d 100644
--- a/src/main.vala
+++ b/src/main.vala
@@ -7,7 +7,9 @@ main (string[] args)
Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.GNOMELOCALEDIR);
Intl.textdomain (Config.GETTEXT_PACKAGE);
- var service = new BluetoothIndicator ();
+ var bluetooth = new Bluez (new KillSwitch ());
+ var service = new BluetoothIndicator (bluetooth);
+
service.run ();
return Posix.EXIT_SUCCESS;
diff --git a/src/org-bluez.vala b/src/org-bluez.vala
new file mode 100644
index 0000000..49c8e4d
--- /dev/null
+++ b/src/org-bluez.vala
@@ -0,0 +1,293 @@
+/* Generated by vala-dbus-binding-tool 0.4.0. Do not modify! */
+/* Generated with: vala-dbus-binding-tool --gdbus --directory=. */
+using GLib;
+
+namespace org {
+
+ namespace bluez {
+
+ [DBus (name = "org.bluez.Manager", timeout = 120000)]
+ public interface Manager : GLib.Object {
+
+ [DBus (name = "GetProperties")]
+ public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
+
+ [DBus (name = "DefaultAdapter")]
+ public abstract GLib.ObjectPath default_adapter() throws DBusError, IOError;
+
+ [DBus (name = "FindAdapter")]
+ public abstract GLib.ObjectPath find_adapter(string pattern) throws DBusError, IOError;
+
+ [DBus (name = "ListAdapters")]
+ public abstract GLib.ObjectPath[] list_adapters() throws DBusError, IOError;
+
+ [DBus (name = "PropertyChanged")]
+ public signal void property_changed(string name, GLib.Variant value);
+
+ [DBus (name = "AdapterAdded")]
+ public signal void adapter_added(GLib.ObjectPath adapter);
+
+ [DBus (name = "AdapterRemoved")]
+ public signal void adapter_removed(GLib.ObjectPath adapter);
+
+ [DBus (name = "DefaultAdapterChanged")]
+ public signal void default_adapter_changed(GLib.ObjectPath adapter);
+ }
+
+ [DBus (name = "org.bluez.Manager", timeout = 120000)]
+ public interface ManagerSync : GLib.Object {
+
+ [DBus (name = "GetProperties")]
+ public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
+
+ [DBus (name = "DefaultAdapter")]
+ public abstract GLib.ObjectPath default_adapter() throws DBusError, IOError;
+
+ [DBus (name = "FindAdapter")]
+ public abstract GLib.ObjectPath find_adapter(string pattern) throws DBusError, IOError;
+
+ [DBus (name = "ListAdapters")]
+ public abstract GLib.ObjectPath[] list_adapters() throws DBusError, IOError;
+
+ [DBus (name = "PropertyChanged")]
+ public signal void property_changed(string name, GLib.Variant value);
+
+ [DBus (name = "AdapterAdded")]
+ public signal void adapter_added(GLib.ObjectPath adapter);
+
+ [DBus (name = "AdapterRemoved")]
+ public signal void adapter_removed(GLib.ObjectPath adapter);
+
+ [DBus (name = "DefaultAdapterChanged")]
+ public signal void default_adapter_changed(GLib.ObjectPath adapter);
+ }
+
+ [DBus (name = "org.bluez.Adapter", timeout = 120000)]
+ public interface Adapter : GLib.Object {
+
+ [DBus (name = "GetProperties")]
+ public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
+
+ [DBus (name = "SetProperty")]
+ public abstract void set_property(string name, GLib.Variant value) throws DBusError, IOError;
+
+ [DBus (name = "RequestSession")]
+ public abstract void request_session() throws DBusError, IOError;
+
+ [DBus (name = "ReleaseSession")]
+ public abstract void release_session() throws DBusError, IOError;
+
+ [DBus (name = "StartDiscovery")]
+ public abstract void start_discovery() throws DBusError, IOError;
+
+ [DBus (name = "StopDiscovery")]
+ public abstract void stop_discovery() throws DBusError, IOError;
+
+ [DBus (name = "ListDevices")]
+ public abstract GLib.ObjectPath[] list_devices() throws DBusError, IOError;
+
+ [DBus (name = "CreateDevice")]
+ public abstract GLib.ObjectPath create_device(string address) throws DBusError, IOError;
+
+ [DBus (name = "CreatePairedDevice")]
+ public abstract GLib.ObjectPath create_paired_device(string address, GLib.ObjectPath agent, string capability) throws DBusError, IOError;
+
+ [DBus (name = "CancelDeviceCreation")]
+ public abstract void cancel_device_creation(string address) throws DBusError, IOError;
+
+ [DBus (name = "RemoveDevice")]
+ public abstract void remove_device(GLib.ObjectPath device) throws DBusError, IOError;
+
+ [DBus (name = "FindDevice")]
+ public abstract GLib.ObjectPath find_device(string address) throws DBusError, IOError;
+
+ [DBus (name = "RegisterAgent")]
+ public abstract void register_agent(GLib.ObjectPath agent, string capability) throws DBusError, IOError;
+
+ [DBus (name = "UnregisterAgent")]
+ public abstract void unregister_agent(GLib.ObjectPath agent) throws DBusError, IOError;
+
+ [DBus (name = "PropertyChanged")]
+ public signal void property_changed(string name, GLib.Variant value);
+
+ [DBus (name = "DeviceCreated")]
+ public signal void device_created(GLib.ObjectPath device);
+
+ [DBus (name = "DeviceRemoved")]
+ public signal void device_removed(GLib.ObjectPath device);
+
+ [DBus (name = "DeviceFound")]
+ public signal void device_found(string address, GLib.HashTable<string, GLib.Variant> values);
+
+ [DBus (name = "DeviceDisappeared")]
+ public signal void device_disappeared(string address);
+ }
+
+ [DBus (name = "org.bluez.Adapter", timeout = 120000)]
+ public interface AdapterSync : GLib.Object {
+
+ [DBus (name = "GetProperties")]
+ public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
+
+ [DBus (name = "SetProperty")]
+ public abstract void set_property(string name, GLib.Variant value) throws DBusError, IOError;
+
+ [DBus (name = "RequestSession")]
+ public abstract void request_session() throws DBusError, IOError;
+
+ [DBus (name = "ReleaseSession")]
+ public abstract void release_session() throws DBusError, IOError;
+
+ [DBus (name = "StartDiscovery")]
+ public abstract void start_discovery() throws DBusError, IOError;
+
+ [DBus (name = "StopDiscovery")]
+ public abstract void stop_discovery() throws DBusError, IOError;
+
+ [DBus (name = "ListDevices")]
+ public abstract GLib.ObjectPath[] list_devices() throws DBusError, IOError;
+
+ [DBus (name = "CreateDevice")]
+ public abstract GLib.ObjectPath create_device(string address) throws DBusError, IOError;
+
+ [DBus (name = "CreatePairedDevice")]
+ public abstract GLib.ObjectPath create_paired_device(string address, GLib.ObjectPath agent, string capability) throws DBusError, IOError;
+
+ [DBus (name = "CancelDeviceCreation")]
+ public abstract void cancel_device_creation(string address) throws DBusError, IOError;
+
+ [DBus (name = "RemoveDevice")]
+ public abstract void remove_device(GLib.ObjectPath device) throws DBusError, IOError;
+
+ [DBus (name = "FindDevice")]
+ public abstract GLib.ObjectPath find_device(string address) throws DBusError, IOError;
+
+ [DBus (name = "RegisterAgent")]
+ public abstract void register_agent(GLib.ObjectPath agent, string capability) throws DBusError, IOError;
+
+ [DBus (name = "UnregisterAgent")]
+ public abstract void unregister_agent(GLib.ObjectPath agent) throws DBusError, IOError;
+
+ [DBus (name = "PropertyChanged")]
+ public signal void property_changed(string name, GLib.Variant value);
+
+ [DBus (name = "DeviceCreated")]
+ public signal void device_created(GLib.ObjectPath device);
+
+ [DBus (name = "DeviceRemoved")]
+ public signal void device_removed(GLib.ObjectPath device);
+
+ [DBus (name = "DeviceFound")]
+ public signal void device_found(string address, GLib.HashTable<string, GLib.Variant> values);
+
+ [DBus (name = "DeviceDisappeared")]
+ public signal void device_disappeared(string address);
+ }
+
+ [DBus (name = "org.bluez.Agent", timeout = 120000)]
+ public interface Agent : GLib.Object {
+
+ [DBus (name = "Authorize")]
+ public abstract void authorize(GLib.ObjectPath device, string uuid) throws DBusError, IOError;
+
+ [DBus (name = "RequestPinCode")]
+ public abstract string request_pin_code(GLib.ObjectPath device) throws DBusError, IOError;
+
+ [DBus (name = "DisplayPasskey")]
+ public abstract void display_passkey(GLib.ObjectPath device, uint passkey) throws DBusError, IOError;
+
+ [DBus (name = "Release")]
+ public abstract void release() throws DBusError, IOError;
+
+ [DBus (name = "Cancel")]
+ public abstract void cancel() throws DBusError, IOError;
+
+ [DBus (name = "RequestConfirmation")]
+ public abstract void request_confirmation(GLib.ObjectPath device, uint passkey) throws DBusError, IOError;
+
+ [DBus (name = "ConfirmModeChange")]
+ public abstract void confirm_mode_change(string mode) throws DBusError, IOError;
+
+ [DBus (name = "RequestPasskey")]
+ public abstract uint request_passkey(GLib.ObjectPath device) throws DBusError, IOError;
+ }
+
+ [DBus (name = "org.bluez.Agent", timeout = 120000)]
+ public interface AgentSync : GLib.Object {
+
+ [DBus (name = "Authorize")]
+ public abstract void authorize(GLib.ObjectPath device, string uuid) throws DBusError, IOError;
+
+ [DBus (name = "RequestPinCode")]
+ public abstract string request_pin_code(GLib.ObjectPath device) throws DBusError, IOError;
+
+ [DBus (name = "DisplayPasskey")]
+ public abstract void display_passkey(GLib.ObjectPath device, uint passkey) throws DBusError, IOError;
+
+ [DBus (name = "Release")]
+ public abstract void release() throws DBusError, IOError;
+
+ [DBus (name = "Cancel")]
+ public abstract void cancel() throws DBusError, IOError;
+
+ [DBus (name = "RequestConfirmation")]
+ public abstract void request_confirmation(GLib.ObjectPath device, uint passkey) throws DBusError, IOError;
+
+ [DBus (name = "ConfirmModeChange")]
+ public abstract void confirm_mode_change(string mode) throws DBusError, IOError;
+
+ [DBus (name = "RequestPasskey")]
+ public abstract uint request_passkey(GLib.ObjectPath device) throws DBusError, IOError;
+ }
+
+ [DBus (name = "org.bluez.Device", timeout = 120000)]
+ public interface Device : GLib.Object {
+
+ [DBus (name = "GetProperties")]
+ public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
+
+ [DBus (name = "SetProperty")]
+ public abstract void set_property(string name, GLib.Variant value) throws DBusError, IOError;
+
+ [DBus (name = "DiscoverServices")]
+ public abstract GLib.HashTable<uint, string> discover_services(string pattern) throws DBusError, IOError;
+
+ [DBus (name = "CancelDiscovery")]
+ public abstract void cancel_discovery() throws DBusError, IOError;
+
+ [DBus (name = "Disconnect")]
+ public abstract void disconnect() throws DBusError, IOError;
+
+ [DBus (name = "PropertyChanged")]
+ public signal void property_changed(string name, GLib.Variant value);
+
+ [DBus (name = "DisconnectRequested")]
+ public signal void disconnect_requested();
+ }
+
+ [DBus (name = "org.bluez.Device", timeout = 120000)]
+ public interface DeviceSync : GLib.Object {
+
+ [DBus (name = "GetProperties")]
+ public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
+
+ [DBus (name = "SetProperty")]
+ public abstract void set_property(string name, GLib.Variant value) throws DBusError, IOError;
+
+ [DBus (name = "DiscoverServices")]
+ public abstract GLib.HashTable<uint, string> discover_services(string pattern) throws DBusError, IOError;
+
+ [DBus (name = "CancelDiscovery")]
+ public abstract void cancel_discovery() throws DBusError, IOError;
+
+ [DBus (name = "Disconnect")]
+ public abstract void disconnect() throws DBusError, IOError;
+
+ [DBus (name = "PropertyChanged")]
+ public signal void property_changed(string name, GLib.Variant value);
+
+ [DBus (name = "DisconnectRequested")]
+ public signal void disconnect_requested();
+ }
+ }
+}
diff --git a/src/phone.vala b/src/phone.vala
index 2abcf11..a2a9917 100644
--- a/src/phone.vala
+++ b/src/phone.vala
@@ -29,7 +29,7 @@ class PhoneMenu: BluetoothMenu
group.insert (actions[i]);
}
- public PhoneMenu ()
+ public PhoneMenu (Bluetooth bluetooth)
{
base ("phone");
diff --git a/src/service.vala b/src/service.vala
index b6ae0f3..0f3d779 100644
--- a/src/service.vala
+++ b/src/service.vala
@@ -28,24 +28,27 @@ public class BluetoothIndicator
private List<BluetoothMenuItem> device_items;
private Dbusmenu.Menuitem menu;
- public BluetoothIndicator () throws Error
+ public BluetoothIndicator (Bluetooth bluetooth)
{
- var phone = new PhoneMenu ();
- var desktop = new DesktopMenu ();
+ var phone = new PhoneMenu (bluetooth);
+ var desktop = new DesktopMenu (bluetooth);
- this.menus = new HashTable<string, BluetoothMenu> (str_hash, str_equal);
- this.menus.insert ("phone", phone);
- this.menus.insert ("desktop", desktop);
+ this.menus = new HashTable<string, BluetoothMenu> (str_hash, str_equal);
+ this.menus.insert ("phone", phone);
+ this.menus.insert ("desktop", desktop);
- this.actions = new SimpleActionGroup ();
- phone.add_actions_to_group (this.actions);
- desktop.add_actions_to_group (this.actions);
+ 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.old");
menu_server = new Dbusmenu.Server ("/com/canonical/indicator/bluetooth/menu");
diff --git a/vapi/rfkill.vapi b/vapi/rfkill.vapi
new file mode 100644
index 0000000..7bfd16d
--- /dev/null
+++ b/vapi/rfkill.vapi
@@ -0,0 +1,44 @@
+// (C) Michael 'Mickey' Lauer <mickey@vanille-media.de>
+// LGPL2
+// scheduled for inclusion in linux.vapi
+
+namespace Linux
+{
+ /*
+ * RfKill
+ */
+ [CCode (cname = "struct rfkill_event", cheader_filename = "linux/rfkill.h")]
+ public struct RfKillEvent {
+ public uint32 idx;
+ public RfKillType type;
+ public RfKillOp op;
+ public uint8 soft;
+ public uint8 hard;
+ }
+
+ [CCode (cname = "guint8", cprefix = "RFKILL_OP_", cheader_filename = "linux/rfkill.h")]
+ public enum RfKillOp {
+ ADD,
+ DEL,
+ CHANGE,
+ CHANGE_ALL
+ }
+
+ [CCode (cname = "guint8", cprefix = "RFKILL_STATE_", cheader_filename = "linux/rfkill.h")]
+ public enum RfKillState {
+ SOFT_BLOCKED,
+ UNBLOCKED,
+ HARD_BLOCKED
+ }
+
+ [CCode (cname = "guint8", cprefix = "RFKILL_TYPE_", cheader_filename = "linux/rfkill.h")]
+ public enum RfKillType {
+ ALL,
+ WLAN,
+ BLUETOOTH,
+ UWB,
+ WIMAX,
+ WWAN
+ }
+
+} /* namespace Linux */