binding: bluetooth: switch from dbus calls to system binding
[apps/mediaplayer.git] / app / api / BluetoothManager.qml
1 /*
2  * Copyright (C) 2016 The Qt Company Ltd.
3  * Copyright (C) 2017 Konsulko Group
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 import QtQuick 2.6
19 import QtWebSockets 1.0
20
21 WebSocket {
22     id: root
23     active: true
24     url: bindingAddress
25
26     property string statusString: "waiting..."
27     property string apiString: "Bluetooth-Manager"
28     property var verbs: []
29     property string payloadLength: "9999"
30
31     property string deviceAddress: ""
32     property bool connected: false
33     property bool av_connected: false
34
35     property int position: 0
36     property int duration: 0
37
38     property string artist: ""
39     property string title: ""
40     property string state: "stopped"
41
42     // AVRCP Target UUID
43     property string avrcp_uuid: "0000110e-0000-1000-8000-00805f9b34fb"
44
45     // A2DP Source
46     property string a2dp_uuid:  "0000110a-0000-1000-8000-00805f9b34fb"
47
48     readonly property var msgid: {
49         "call": 2,
50         "retok": 3,
51         "reterr": 4,
52         "event": 5
53     }
54
55     onTextMessageReceived: {
56         var json = JSON.parse(message)
57         console.debug("Raw response: " + message)
58         var request = json[2].request
59         var response = json[2].response
60         console.debug("response: " + JSON.stringify(response))
61         switch (json[0]) {
62             case msgid.call:
63                 break
64             case msgid.retok:
65                 root.statusString = request.status
66                 var address = ""
67
68                 if (request.info == "BT - Scan Result is Displayed") {
69                     for (var i = 0; i < response.length; i++) {
70                         var data = response[i]
71                         if (data.Connected == "True" && data.UUIDs.indexOf(avrcp_uuid) >= 0) {
72                             address = response[i].Address
73                             console.debug("Connected Device: " + address)
74
75                             root.connected = true
76                             player.pause()
77
78                             //NOTE: This hack is here for when MediaPlayer is started
79                             //      with an existing connection.
80                             if (data.AVPConnected == "True") {
81                                 root.av_connected = true
82                             }
83                         }
84                     }
85                     root.deviceAddress = address
86                     if (!address) {
87                         root.connected = false
88                         playlistview.visible = true
89                     }
90                 }
91                 break
92             case msgid.reterr:
93                 root.statusString = "Bad return value, binding probably not installed"
94                 break
95             case msgid.event:
96                 var payload = JSON.parse(JSON.stringify(json[2]))
97                 var event = payload.event
98
99                 if (event == "Bluetooth-Manager/connection") {
100                     sendSocketMessage("discovery_result", 'None')
101                 } else if (event == "Bluetooth-Manager/device_updated") {
102                     var data = payload.data
103                     var metadata = data.Metadata
104
105                     if (root.deviceAddress != data.Address)
106                         break
107
108                     if (data.Connected == "False") {
109                         console.debug("Device Disconnected")
110                         sendSocketMessage("discovery_result", 'None')
111                         break
112                     }
113                     root.av_connected = data.AVPConnected == "True"
114
115                     if ('Position' in metadata) {
116                         console.debug("Position " + metadata.Position)
117                         root.position = metadata.Position
118                     }
119
120                     if ('Duration' in metadata) {
121                         console.debug("Duration " + metadata.Duration)
122                         root.duration = metadata.Duration
123                     }
124
125                     if ('Status' in metadata) {
126                         console.debug("Status " + metadata.Status)
127                         root.state = metadata.Status
128                     }
129
130                     if ('Artist' in metadata) {
131                         console.debug("Artist " + metadata.Artist)
132                         root.artist = metadata.Artist
133                     }
134
135                     if ('Title' in metadata) {
136                         console.debug("Title " + metadata.Title)
137                         root.title = metadata.Title
138                     }
139                 }
140                 break
141         }
142     }
143
144     onStatusChanged: {
145         switch (status) {
146             case WebSocket.Open:
147             console.debug("onStatusChanged: Open")
148             sendSocketMessage("eventadd", { "tag" : "device_updated", "name" : "device_updated" })
149             sendSocketMessage("eventsub", { "tag" : "device_updated" })
150             sendSocketMessage("eventadd", { "tag" : "connection", "name" : "connection" })
151             sendSocketMessage("eventsub", { "tag" : "connection" })
152             sendSocketMessage("discovery_result", 'None')
153             break
154             case WebSocket.Error:
155             root.statusString = "WebSocket error: " + root.errorString
156             break
157         }
158     }
159
160     function sendSocketMessage(verb, parameter) {
161         var requestJson = [ msgid.call, payloadLength, apiString + '/'
162         + verb, parameter ]
163         console.debug("sendSocketMessage: " + JSON.stringify(requestJson))
164         verbs.push(verb)
165         root.sendTextMessage(JSON.stringify(requestJson))
166     }
167
168     function sendMediaCommand(state) {
169         var parameters = { "Address": deviceAddress, "value": state }
170         sendSocketMessage("set_avrcp_controls", parameters)
171     }
172
173     function connect_profiles() {
174         sendSocketMessage("connect", { "value": root.deviceAddress, "uuid": a2dp_uuid })
175         sendSocketMessage("connect", { "value": root.deviceAddress, "uuid": avrcp_uuid })
176         root.av_connected = true
177     }
178
179     function disconnect_profiles() {
180         sendSocketMessage("disconnect", { "value": root.deviceAddress, "uuid": a2dp_uuid })
181         sendSocketMessage("disconnect", { "value": root.deviceAddress, "uuid": avrcp_uuid })
182     }
183 }