aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCharles Kerr <charles.kerr@canonical.com>2013-10-11 08:38:51 -0500
committerCharles Kerr <charles.kerr@canonical.com>2013-10-11 08:38:51 -0500
commitf7ca11b202e442e759cca86a70d9c6d027e82e76 (patch)
tree144aabb1f6df9fa060bd4418fb26857d5055dc75 /src
parent3145f10632a3ce7ee33e8cdaa78401d7eb881f4e (diff)
downloadayatana-indicator-bluetooth-f7ca11b202e442e759cca86a70d9c6d027e82e76.tar.gz
ayatana-indicator-bluetooth-f7ca11b202e442e759cca86a70d9c6d027e82e76.tar.bz2
ayatana-indicator-bluetooth-f7ca11b202e442e759cca86a70d9c6d027e82e76.zip
if /dev/rfkill doesn't exist or isn't writable, then try to handle bluetooth toggles simply by toggling bluez Adapters' Powered property
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth.vala49
-rw-r--r--src/bluez.vala121
-rw-r--r--src/desktop.vala6
-rw-r--r--src/killswitch.vala7
-rw-r--r--src/phone.vala2
-rw-r--r--src/profile.vala13
6 files changed, 128 insertions, 70 deletions
diff --git a/src/bluetooth.vala b/src/bluetooth.vala
index 100bdf2..b268701 100644
--- a/src/bluetooth.vala
+++ b/src/bluetooth.vala
@@ -27,22 +27,19 @@ public interface Bluetooth: Object
This work as a proxy for "does this hardware support bluetooth?" */
public abstract bool supported { get; protected set; }
- /* True if there are any bluetooth adapters powered up on the system.
- In short, whether or not this system's bluetooth is "on". */
- public abstract bool powered { get; protected set; }
+ /* True if bluetooth's enabled on this system.
+ Bluetooth can be soft-blocked by software and hard-blocked physically,
+ eg by a laptop's network killswitch */
+ public abstract bool enabled { get; protected set; }
+
+ /* Try to enable/disable bluetooth. This can fail if it's overridden
+ by the system, eg by a laptop's network killswitch */
+ public abstract void try_set_enabled (bool b);
/* True if our system can be seen by other bluetooth devices */
public abstract bool discoverable { get; protected set; }
public abstract void try_set_discoverable (bool discoverable);
- /* True if bluetooth's blocked. This can be soft-blocked by software and
- * hard-blocked physically, eg by a laptop's network killswitch */
- public abstract bool blocked { get; protected set; }
-
- /* Try to block/unblock bluetooth. This can fail if it's overridden
- by the system, eg by a laptop's network killswitch */
- public abstract void try_set_blocked (bool b);
-
/* Get a list of the Device structs that we know about */
public abstract List<unowned Device> get_devices ();
@@ -53,33 +50,3 @@ public interface Bluetooth: Object
The device_key argument comes from the Device struct */
public abstract void set_device_connected (uint device_key, bool connected);
}
-
-
-
-/**
- * Base class for Bluetooth objects that use a killswitch to implement
- * the 'discoverable' property.
- */
-public abstract class KillswitchBluetooth: Object, Bluetooth
-{
- private KillSwitch killswitch;
-
- public KillswitchBluetooth (KillSwitch killswitch)
- {
- // always sync our 'blocked' property with the one in killswitch
- this.killswitch = killswitch;
- blocked = killswitch.blocked;
- killswitch.notify["blocked"].connect (() => blocked = killswitch.blocked );
- }
-
- public bool supported { get; protected set; default = false; }
- public bool powered { get; protected set; default = false; }
- public bool discoverable { get; protected set; default = false; }
- public bool blocked { get; protected set; default = true; }
- public void try_set_blocked (bool b) { killswitch.try_set_blocked (b); }
-
- // empty implementations
- public abstract void try_set_discoverable (bool b);
- public abstract List<unowned Device> get_devices ();
- public abstract void set_device_connected (uint device_key, bool connected);
-}
diff --git a/src/bluez.vala b/src/bluez.vala
index 8c8c1b6..82f34f4 100644
--- a/src/bluez.vala
+++ b/src/bluez.vala
@@ -22,12 +22,25 @@
/**
* Bluetooth implementaion which uses org.bluez on DBus
*/
-public class Bluez: KillswitchBluetooth
+public class Bluez: Bluetooth, Object
{
uint next_device_id = 1;
org.bluez.Manager manager;
org.bluez.Adapter default_adapter;
+ private bool _powered = false;
+
+ private bool powered {
+ get { return _powered; }
+ set { _powered = value; update_enabled(); }
+ }
+
+ private KillSwitch killswitch = null;
+
+ private string adapter_path = null;
+
+ private DBusConnection bus = null;
+
/* maps an org.bluez.Device's object_path to the org.bluez.Device proxy */
HashTable<string,org.bluez.Device> path_to_proxy;
@@ -42,42 +55,85 @@ public class Bluez: KillswitchBluetooth
public Bluez (KillSwitch killswitch)
{
- base (killswitch);
+ try
+ {
+ bus = Bus.get_sync (BusType.SYSTEM);
+ }
+ catch (Error e)
+ {
+ critical (@"$(e.message)");
+ }
- string adapter_path = null;
+ if (killswitch.is_valid())
+ {
+ this.killswitch = killswitch;
+ killswitch.notify["blocked"].connect (() => update_enabled());
+ update_enabled ();
+ }
id_to_path = new HashTable<uint,string> (direct_hash, direct_equal);
id_to_device = new HashTable<uint,Device> (direct_hash, direct_equal);
path_to_id = new HashTable<string,uint> (str_hash, str_equal);
path_to_proxy = new HashTable<string,org.bluez.Device> (str_hash, str_equal);
+ reset_manager ();
+ }
+
+ private void reset_manager ()
+ {
+ string new_adapter_path = null;
try
{
- manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", "/");
+ manager = bus.get_proxy_sync ("org.bluez", "/");
- // get the current default adapter & watch for future default adapters
- adapter_path = manager.default_adapter ();
+ // if the default adapter changes, update our connections
manager.default_adapter_changed.connect ((object_path)
=> on_default_adapter_changed (object_path));
+
+ // if the current adapter disappears, call clear_adapter()
+ manager.adapter_removed.connect ((object_path) => {
+ if (object_path == adapter_path)
+ clear_adapter ();
+ });
+
+ // get the current default adapter & watch for future default adapters
+ new_adapter_path = manager.default_adapter ();
}
catch (Error e)
{
critical (@"$(e.message)");
}
- on_default_adapter_changed (adapter_path);
+ on_default_adapter_changed (new_adapter_path);
}
- private void on_default_adapter_changed (string? object_path)
+ private void clear_adapter ()
{
- supported = object_path != null;
+ if (adapter_path != null)
+ debug (@"clearing adapter; was using $adapter_path");
+
+ path_to_proxy.remove_all ();
+ path_to_id.remove_all ();
+ id_to_path.remove_all ();
+ id_to_device.remove_all ();
+
+ default_adapter = null;
+ adapter_path = null;
+
+ discoverable = false;
+ powered = false;
+ }
+
+ void on_default_adapter_changed (string? object_path)
+ {
+ clear_adapter ();
if (object_path != null) try
{
- debug (@"using default adapter at $object_path");
+ adapter_path = object_path;
default_adapter = Bus.get_proxy_sync (BusType.SYSTEM,
"org.bluez",
- object_path);
+ adapter_path);
default_adapter.property_changed.connect (()
=> on_default_adapter_properties_changed ());
@@ -104,6 +160,8 @@ public class Bluez: KillswitchBluetooth
on_default_adapter_properties_changed ();
}
+ /* When the default adapter's properties change,
+ update our own properties "powered" and "discoverable" */
private void on_default_adapter_properties_changed ()
{
bool is_discoverable = false;
@@ -217,7 +275,6 @@ public class Bluez: KillswitchBluetooth
private void device_connect_on_interface (DBusProxy proxy,
string interface_name)
{
- var bus = proxy.get_connection ();
var object_path = proxy.get_object_path ();
debug (@"trying to connect to $object_path: $(interface_name)");
@@ -359,11 +416,21 @@ public class Bluez: KillswitchBluetooth
devices_changed ();
}
+ /* update the 'enabled' property by looking at the killswitch state
+ and the 'powered' property state */
+ void update_enabled ()
+ {
+ var blocked = (killswitch != null) && killswitch.blocked;
+ debug (@"in upate_enabled, powered is $powered, blocked is $blocked");
+ enabled = powered && !blocked;
+ }
+
+
////
//// Public API
////
- public override void set_device_connected (uint id, bool connected)
+ public void set_device_connected (uint id, bool connected)
{
var device = id_to_device.lookup (id);
var path = id_to_path.lookup (id);
@@ -380,7 +447,7 @@ public class Bluez: KillswitchBluetooth
}
}
- public override void try_set_discoverable (bool b)
+ public void try_set_discoverable (bool b)
{
if (discoverable != b) try
{
@@ -392,8 +459,32 @@ public class Bluez: KillswitchBluetooth
}
}
- public override List<unowned Device> get_devices ()
+ public List<unowned Device> get_devices ()
{
return id_to_device.get_values();
}
+
+ public bool supported { get; protected set; default = false; }
+ public bool discoverable { get; protected set; default = false; }
+ public bool enabled { get; protected set; default = false; }
+
+ public void try_set_enabled (bool b)
+ {
+ if (killswitch != null)
+ {
+ debug (@"setting killswitch blocked to $(!b)");
+ killswitch.try_set_blocked (!b);
+ }
+
+ if (default_adapter != null) try
+ {
+ debug (@"setting bluez Adapter's Powered property to $b");
+ default_adapter.set_property ("Powered", new Variant.boolean (b));
+ powered = b;
+ }
+ catch (Error e)
+ {
+ critical (@"$(e.message)");
+ }
+ }
}
diff --git a/src/desktop.vala b/src/desktop.vala
index 7c99a45..a30935a 100644
--- a/src/desktop.vala
+++ b/src/desktop.vala
@@ -82,7 +82,7 @@ class Desktop: Profile
void update_visibility ()
{
- visible = bluetooth.powered && !bluetooth.blocked && settings.get_boolean("visible");
+ visible = bluetooth.enabled && settings.get_boolean("visible");
}
///
@@ -229,10 +229,6 @@ class Desktop: Profile
bluetooth.notify["discoverable"].connect (()
=> action.set_state (bluetooth.discoverable));
- action.set_enabled (bluetooth.powered);
- bluetooth.notify["powered"].connect (()
- => action.set_enabled (bluetooth.powered));
-
return action;
}
diff --git a/src/killswitch.vala b/src/killswitch.vala
index 08ee0cc..167d189 100644
--- a/src/killswitch.vala
+++ b/src/killswitch.vala
@@ -26,6 +26,8 @@
*/
public interface KillSwitch: Object
{
+ public abstract bool is_valid ();
+
public abstract bool blocked { get; protected set; }
/* Try to block/unblock bluetooth.
@@ -109,6 +111,11 @@ public class RfKillSwitch: KillSwitch, Object
}
}
+ public bool is_valid ()
+ {
+ return fd != -1;
+ }
+
private bool on_channel_event (IOChannel source, IOCondition condition)
{
read_event ();
diff --git a/src/phone.vala b/src/phone.vala
index 18c698c..2b0b96b 100644
--- a/src/phone.vala
+++ b/src/phone.vala
@@ -53,7 +53,7 @@ class Phone: Profile
void update_visibility ()
{
- visible = bluetooth.powered && !bluetooth.blocked;
+ visible = bluetooth.enabled;
}
///
diff --git a/src/profile.vala b/src/profile.vala
index c32e46b..584af56 100644
--- a/src/profile.vala
+++ b/src/profile.vala
@@ -123,16 +123,16 @@ class Profile: Object
{
var action = new SimpleAction.stateful ("bluetooth-enabled",
null,
- !bluetooth.blocked);
+ bluetooth.enabled);
action.activate.connect (()
=> action.change_state (!action.get_state().get_boolean()));
action.change_state.connect ((action, requestedValue)
- => bluetooth.try_set_blocked (!requestedValue.get_boolean()));
+ => bluetooth.try_set_enabled (requestedValue.get_boolean()));
- bluetooth.notify["blocked"].connect (()
- => action.set_state (!bluetooth.blocked));
+ bluetooth.notify["enabled"].connect (()
+ => action.set_state (bluetooth.enabled));
return action;
}
@@ -144,12 +144,9 @@ class Profile: Object
protected Variant action_state_for_root ()
{
- var blocked = bluetooth.blocked;
- var powered = bluetooth.powered;
-
string a11y;
string icon_name;
- if (powered && !blocked)
+ if (bluetooth.enabled)
{
a11y = "Bluetooth (on)";
icon_name = "bluetooth-active";