Monitor settings daemon events and update changes
[profile/ivi/SettingsApp.git] / js / panel-bluetooth.js
1 /*
2  * Copyright (c) 2013, Intel Corporation.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 function bluetoothPanelInit() {
11
12     /* Bluetooth Settings Panel */
13     $('#page_bluetooth').on('pageshow', function(event, data) {
14         if (data.prevPage.attr('id') === 'page_bluetooth_detail') return;
15
16         settings.bluetooth.subscribeEvents(bluetoothEventReceived);
17         var adapter = settings.bluetooth.getDefaultAdapter();
18         if (adapter === null) {
19             showMsg('Error', 'Bluetooth adapter not found');
20             return;
21         }
22         console.log('Default BT adapter: ', adapter.name);
23
24         if (adapter.name != undefined) {
25             $('#label_bluetooth_adapter').html(adapter.name);
26         } else {
27             $('#label_bluetooth_adapter').html('Bluetooth adapter not found');
28         }
29
30         if (adapter.powered) {
31             bluetoothToggleOn();
32             adapter.stopScanDevices(function() {
33                 bluetoothStartScan(adapter);
34             }, null);
35         } else {
36             bluetoothToggleOff();
37         }
38     });
39
40     $('#toggle_bluetooth').change(function() {
41         var adapter = settings.bluetooth.getDefaultAdapter();
42         if (adapter === null) {
43             showMsg('Error', 'Bluetooth adapter not found');
44             bluetoothToggleOff();
45             return;
46         }
47
48         if ($('#toggle_bluetooth').val() === 'off') {
49             /* stop scan, then disable bluetooth */
50             adapter.stopScanDevices(function() {
51                 /* success */
52                 console.log('Bluetooth scan canceled');
53                 $('#button_bluetooth_scan .ui-btn-text').text('Scan');
54                 adapter.setPowered(false, function() {
55                     /* success */
56                     console.log('Power off adapter success, adapter is powered: ' + adapter.powered);
57                     bluetoothToggleOff();
58                 }, function(e) {
59                     /* error */
60                     bluetoothToggleOn();
61                     showMsg('Error', 'Cannot turn off bluetooth adapter: ' + e);
62                 });
63             }, function(e) {
64                 /* error */
65                 $('#toggle_bluetooth').val('on').slider('refresh');
66                 showMsg('Error', 'Cannot cancel scan: ' + e);
67             });
68         } else {
69             adapter.setPowered(true, function() {
70                 /* success */
71                 console.log('Power on adapter success, adapter is powered: ' + adapter.powered);
72                 bluetoothToggleOn();
73                 bluetoothStartScan(adapter);
74             }, function(e) {
75                 /* error */
76                 bluetoothToggleOff();
77                 showMsg('Error', 'Cannot turn on bluetooth adapter: ' + e);
78             });
79         }
80     });
81
82     $('#button_bluetooth_scan').on('click', function() {
83         var adapter = settings.bluetooth.getDefaultAdapter();
84         if (adapter === null) {
85             showMsg('Error', 'Bluetooth adapter not found');
86             return;
87         }
88         if ($('#button_bluetooth_scan').text() === 'Scan') {
89             bluetoothStartScan(adapter);
90         } else {
91             bluetoothStopScan(adapter);
92         }
93     });
94
95     /* Bluetooth device detail page */
96     $('#page_bluetooth_detail').on('pageshow', function(event, data) {
97         var device_id = localStorage.getItem('bluetooth_device_id');
98         if (device_id == undefined) return;
99         var device = $(jqId(device_id)).data('device-object');
100         bluetoothConstructDetailPanel(device);
101     });
102 }
103
104 function bluetoothEventReceived(event) {
105     if (event.type !== WS_EVENT_TYPE.BLUETOOTH) return;
106     if ($.mobile.activePage.attr('id') !== 'page_bluetooth' || $.mobile.activePage.attr('id') !== 'page_bluetooth_detail') {
107         return;
108     }
109
110     if (event.name === 'PropertyChanged') {
111         bluetoothHandlePropertyChanged(event.value);
112     } else {
113         console.log('Unsupported bluetooth event received: ' + event.name);
114     }
115 }
116
117 function bluetoothHandlePropertyChanged(property) {
118     if (property[0] === 'Powered') {
119         if (property[1] === true) {
120             bluetoothToggleOn();
121             adapter.stopScanDevices(function() {
122                 bluetoothStartScan(adapter);
123             }, null);
124         } else {
125             bluetoothToggleOff();
126         }
127     }
128 }
129
130 function bluetoothClearAvailableList() {
131     $('#listview_device_available').html('');
132 }
133
134 function bluetoothStartScan(adapter) {
135     /* clear the device list with new scan */
136     bluetoothClearAvailableList();
137
138     adapter.startScanDevices({
139         /* success */
140         onstarted: function() {
141             console.log('Bluetooth scan started...');
142             $('#button_bluetooth_scan .ui-btn-text').text('Stop');
143         },
144         ondevicefound: function(device) {
145             console.log('Bluetoth device found - name: ' + device.name + ', address: ' + device.address + ', is paired: ' + device.paired + ', is connected: ' + device.connected);
146             bluetoothUpdateDevice(device);
147         },
148         ondevicedisappeared: function(address) {
149             if ($(jqId(address)).length) {
150                 bluetoothRemoveFromAvailableList(address);
151             }
152         },
153         onfinished: function(devices) {
154             $('#button_bluetooth_scan .ui-btn-text').text('Scan');
155             for (var i = 0; i < devices.length; i++) {
156                 if (!$(jqId(devices[i].address)).length) {
157                     bluetoothUpdateDevice(devices[i]);
158                 }
159             }
160         }
161     }, function(e) {
162         /* error */
163         showMsg('Error', 'Cannot scan: ' + e);
164     });
165 }
166
167 function bluetoothRefreshList() {
168     $('#listview_device_paired').listview('refresh');
169     $('#listview_device_available').listview('refresh');
170 }
171
172 function bluetoothStopScan(adapter) {
173     adapter.stopScanDevices(function() {
174         /* success */
175         console.log('Bluetooth scan canceled');
176         $('#button_bluetooth_scan .ui-btn-text').text('Scan');
177     }, function(e) {
178         /* error */
179         showMsg('Error', 'Cannot cancel scan: ' + e);
180     });
181 }
182
183 function bluetoothAppendToPairedList(device) {
184     if ($('#listview_device_paired').find(jqId(device.address)).length != 0) return;
185
186     var parent = '#listview_device_paired';
187     bluetoothConstructDeviceElement(parent, device);
188     bluetoothUpdateDeviceButton(device);
189     bluetoothRefreshList();
190 }
191
192 function bluetoothRemoveFromPairedList(device_addr) {
193     var removeThis = $('#listview_device_paired li').filter(function() {
194         return $(this).find(jqId(device_addr)).length === 1;
195     });
196
197     if (removeThis.length !== 0) {
198         removeThis.remove();
199         bluetoothRefreshList();
200     }
201 }
202
203 function bluetoothAppendToAvailableList(device) {
204     if ($('#listview_device_available').find(jqId(device.address)).length != 0) return;
205
206     var parent = '#listview_device_available';
207     bluetoothConstructDeviceElement(parent, device);
208     bluetoothUpdateDeviceButton(device);
209     bluetoothRefreshList();
210 }
211
212 function bluetoothRemoveFromAvailableList(device_addr) {
213     var removeThis = $('#listview_device_available li').filter(function() {
214         return $(this).find(jqId(device_addr)).length === 1;
215     });
216
217     if (removeThis.length !== 0) {
218         removeThis.remove();
219         bluetoothRefreshList();
220     }
221 }
222
223 function bluetoothConstructDeviceElement(parent, device) {
224     var html = '<li data-icon="false"><a href="#" id="' + jqId(device.address).replace('#', '') + '">';
225     html += '<img src="images/bluetooth.png" class="device-icon ui-li-icon"></img>';
226     html += '<div class="device-name">' + device.name + '</div>';
227     html += '<div class="device-address">' + device.address + '</div>';
228     html += '<div class="device-status"></div>';
229     html += '<div data-role="button" class="device-action-button ui-li-aside" data-inline="true"></div>';
230     html += '</a></li>';
231     $(parent).append(html).trigger('create');
232
233     /* store device object in the element so we can reference it later */
234     $(jqId(device.address)).data('device-object', device);
235
236     $(jqId(device.address)).on('click', function() {
237         localStorage.setItem('bluetooth_device_id', device.address);
238         $.mobile.changePage('#page_bluetooth_detail');
239     });
240
241     $(jqId(device.address)).find('div.device-action-button').on('click', function(e) {
242         var parent = $(this).parent().attr('id');
243
244         /*
245          * prevent the click event to propagate up
246          */
247         e.stopImmediatePropagation();
248         e.preventDefault();
249
250         var adapter = settings.bluetooth.getDefaultAdapter();
251         if (adapter === null) return;
252
253         /* retrieve the device object from element */
254         var device = $(jqId(parent)).data('device-object');
255         if (device == undefined) {
256             console.error('Bluetooth device not found');
257             return;
258         }
259
260         if (!device.paired) {
261             createPopupDialog(false, false, 'Pair with', device.name, 'Pair', 'Cancel', function() {
262                 console.log('Bluetooth pair with device: ' + device.address);
263                 showSpinner(false, 'Pairing...');
264                 adapter.pairDevice(device.address, function() {
265                     /* success */
266                     hideSpinner();
267                     device.paired = true;
268
269                     /* changing from unpaired to paried */
270                     bluetoothUpdateDevice(device);
271                 }, function(e) {
272                     /* error */
273                     hideSpinner();
274                     showMsg('Error', 'Bluetooth pair failed: ' + e);
275                 });
276             });
277         } else if (device.paired && !device.connected) {
278             console.log('Bluetooth connect with device: ' + device.address);
279             showMsg('Error', 'Not suppported');
280         } else if (device.connected) {
281             console.log('Bluetooth disconnect with device: ' + device.address);
282             showMsg('Error', 'Not suppported');
283         }
284     });
285 }
286
287 function bluetoothUpdateDevice(device) {
288     /* reposition device if it's paired or unpaired */
289     if (device.paired) {
290         bluetoothRemoveFromAvailableList(device.address);
291         bluetoothAppendToPairedList(device);
292     } else {
293         bluetoothRemoveFromPairedList(device.address);
294         bluetoothAppendToAvailableList(device);
295     }
296
297     /* update device button for allowed action */
298     bluetoothUpdateDeviceButton(device);
299
300     /* update device connection status */
301     bluetoothUpdateConnectionStatus(device);
302 }
303
304 function bluetoothUpdateDeviceButton(device) {
305     if (device.paired) {
306         if (device.connected) {
307             $(jqId(device.address)).find('div.device-action-button').find('span').text('Disconnect');
308         } else {
309             $(jqId(device.address)).find('div.device-action-button').find('span').text('Connect');
310         }
311     } else {
312         $(jqId(device.address)).find('div.device-action-button').find('span').text('Pair');
313     }
314 }
315
316 function bluetoothUpdateConnectionStatus(device) {
317     var status = 'unpaired';
318     if (device.paired) {
319         $(jqId(device.address)).addClass('device-paired');
320         if (device.connected) {
321             status = 'connected';
322             $(jqId(device.address)).addClass('device-connected');
323         } else {
324             status = 'disconnected';
325             $(jqId(device.address)).removeClass('device-connected');
326         }
327     } else {
328         $(jqId(device.address)).removeClass('device-paired');
329         $(jqId(device.address)).removeClass('device-connected');
330     }
331
332     bluetoothUpdateConnectionStatusText(device, status);
333 }
334
335 function bluetoothUpdateConnectionStatusText(device, status) {
336     $(jqId(device.address)).find('div.device-status').text(status);
337 }
338
339 function bluetoothConstructDetailPanel(device) {
340     var status_paired = 'No';
341     var status_connected = 'No';
342
343     if (device == null) return;
344     if (device.paired) status_paired = 'Yes';
345     if (device.connected) status_connected = 'Yes';
346
347     $('#page_bluetooth_detail_content').html('');
348     var html = '<ul data-role="listview" id="listview_bluetooth_detail" data-inset="true" ' + 'class="device-list ui-listview">';
349     html += '<li id="bluetooth_detail_name"><h2>Device Name: ' + device.name + '</h2></li>';
350     html += '<li id="bluetooth_detail_address"><h2>Device Address: ' + device.address + '</h2></li>';
351     html += '<li id="bluetooth_detail_paired"><h2>Paired: ' + status_paired + '</h2></li>';
352     html += '<li id="bluetooth_detail_connected"><h2>Connected: ' + status_connected + '</h2></li>';
353     html += '</ul>';
354     $('#page_bluetooth_detail_content').append(html).trigger('create');
355
356     if (device.paired) {
357         html = '<div data-role="button" id="button_bluetooth_unpair">Unpair</div>';
358         $('#page_bluetooth_detail_content').append(html).trigger('create');
359
360         $('#button_bluetooth_unpair').on('click', function(e) {
361             console.log('Bluetooth unpair with device: ' + device.address);
362             var adapter = settings.bluetooth.getDefaultAdapter();
363             if (adapter === null) return;
364
365             createPopupDialog(false, false, 'Unpair with device', device.name, 'Unpair', 'Cancel', function() {
366                 showSpinner(false, 'Unpairing...');
367                 adapter.unpairDevice(device.address, function() {
368                     /* success */
369                     hideSpinner();
370                     device.paired = false;
371                     device.connected = false;
372                     $('#button_bluetooth_unpair').remove();
373
374                     /* changing from paired to unparied */
375                     bluetoothUpdateDevice(device);
376                     setTimeout(function() {
377                         $.mobile.changePage('#page_bluetooth');
378                     }, 1000);
379                 }, function(e) {
380                     /* error */
381                     hideSpinner();
382                     showMsg('Error', 'Bluetooth unpair failed: ' + e);
383
384                     /* Something is wrong, remove from paired list */
385                     bluetoothRemoveFromPairedList(device.address);
386                 });
387             });
388         });
389     }
390     $('#listview_bluetooth_detail').listview('refresh');
391 }
392
393 function bluetoothUpdateDetailPanel(device) {
394     var status_paired = 'No';
395     var status_connected = 'No';
396
397     if (device == null) return;
398     if (device.paired) status_paired = 'Yes';
399     if (device.connected) status_connected = 'Yes';
400     $('#bluetooth_detail_paired').text(connected);
401     $('#bluetooth_detail_connected').text(status_connected);
402     $('#listview_bluetooth_detail').listview('refresh');
403 }
404
405 function bluetoothToggleOn() {
406     setTimeout(function() {
407         $('#bluetooth_devices').show();
408         $('#toggle_bluetooth').val('on').slider('refresh');
409     }, 100);
410 }
411
412 function bluetoothToggleOff() {
413     setTimeout(function() {
414         $('#bluetooth_devices').hide();
415         $('#toggle_bluetooth').val('off').slider('refresh');
416     }, 100);
417 }