Dap.Bluetooth: Extract Gnome specific component
[banshee-community-extensions:banshee-community-extensions.git] / src / Bluetooth / Banshee.Dap.Bluetooth / AdapterManager.fs
1 //
2 // AdapterManager.fs
3 //
4 // Author:
5 //   Nicholas Little <arealityfarbetween@googlemail.com>
6 //
7 // Copyright (c) 2014 Nicholas Little
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26 module Banshee.Dap.Bluetooth.Adapters
27
28 open System.Collections.Generic
29 open System.ComponentModel
30 open Banshee.Dap.Bluetooth.AdapterApi
31 open Banshee.Dap.Bluetooth.GnomeApi
32 open Banshee.Dap.Bluetooth.InversionApi
33 open Banshee.Dap.Bluetooth.SupportApi
34 open Banshee.Dap.Bluetooth.Wrappers
35 open DBus
36 open Hyena.Log
37
38 let tryFind y (dict: IDictionary<_,_>) =
39     if dict.ContainsKey y then Some dict.[y]
40     else None
41
42 type switcher = (bool -> bool)
43
44 type GnomeRfkill() =
45     let ksw =
46         let path = ObjectPath (PATH_GNOME_RFKILL)
47         let ob = Bus.Session.GetObject<IRfkill>(NAME_GNOME, path)
48         let pm = PropertyManager (Bus.Session, NAME_GNOME, path)
49         RfkillWrapper(ob, pm)
50     member x.Set y =
51         let has  = ksw.BluetoothHasAirplaneMode
52         let hard = ksw.BluetoothHardwareAirplaneMode
53         let soft = ksw.BluetoothAirplaneMode
54         let status = (has, hard, soft)
55         Debugf "Killswitch: %A" status
56         match status with
57         | (true, false, soft) when soft <> y ->
58           ksw.BluetoothAirplaneMode <- y; true
59         | (_, _, _) -> false
60
61 type AdapterManager(switch: switcher) =
62     let inv = DBusInverter(Bus.System, NAME_BLUEZ, ObjectPath.Root)
63     let ads = Dictionary<ObjectPath, AdapterWrapper>()
64     let notify = Event<_>()
65     let get_pow () = ads.Values |> Seq.exists (fun a -> a.Powered)
66     let get_dis () = ads.Values |> Seq.exists (fun a -> a.Discovering)
67     let set_pow x = not x |> switch |> ignore
68                     ads.Values |> Seq.iter (fun a -> if x <> a.Powered then a.Powered <- x)
69     let set_dis x = if x then set_pow x
70                     ads.Values |> Seq.iter (fun a -> match (x, a.Discovering) with
71                                                      | (y, z) when y = z -> ()
72                                                      | (true, _) -> a.StartDiscovery()
73                                                      | (false, _) -> a.StopDiscovery())
74     let handle = PropertyChangedEventHandler(fun o x -> notify.Trigger())
75     do
76         inv.Register<IAdapter> (fun o p -> let a = o :?> IAdapter
77                                            AdapterWrapper(a, p) :> obj)
78         inv.ObjectChanged.Add(fun o ->
79           let adapter = o.Object :?> AdapterWrapper
80           match o.Action with
81           | Added -> ads.[o.Path] <- adapter
82                      adapter.PropertyChanged.AddHandler(handle)
83                      notify.Trigger()
84           | Removed -> adapter.PropertyChanged.RemoveHandler(handle)
85                        ads.Remove o.Path |> ignore
86                        notify.Trigger()
87           | _ -> ())
88         inv.Refresh ()
89     member x.Adapters = ads.Keys
90     member x.Adapter y = ads |> tryFind y
91     member x.PowerOn y = switch false |> ignore
92                          ads.[y].Powered <- true
93     member x.Powered with get () = get_pow ()
94                      and set v = set_pow v
95     member x.Discovering with get () = get_dis ()
96                          and set v = set_dis v
97     member x.Notify = notify.Publish