Add the sender name in signal subscribe function
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / audio / bt-service-absolute-volume.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Dohyun Pyun <dh79.pyun@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <vconf.h>
23 #include <vconf-internal-keys.h>
24
25 #include <oal-event.h>
26 #include <oal-hardware.h>
27 #include <oal-audio-src.h>
28
29 #include "bt-service-common.h"
30 #include "bt-service-audio-common.h"
31 #include "bt-service-event.h"
32 #include "bt-service-avrcp-tg.h"
33
34 /* We will remove this flag after stabilizing the functionality */
35 #define AVC_DEBUG 1
36
37 /* Avoid the build error related to vconf.h's dependency */
38 #ifndef VCONFKEY_BT_AVC_MODE
39 #define VCONFKEY_BT_AVC_MODE "db/bluetooth/avc_mode"
40 #endif
41
42 #ifndef VCONFKEY_BT_AVC_OFF
43 #define VCONFKEY_BT_AVC_OFF false
44 #endif
45
46 #define ABSOLUTE_VOLUME_MAX 150
47 #define BT_VOLUME_MAX 127
48
49 static unsigned int absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
50 static unsigned int bt_volume = BT_VOLUME_MAX + 1;
51 static unsigned int avc_mode = BT_AVC_OFF;
52
53 static void __bt_audio_covert_system_to_bt_volume(unsigned int sys_vol, unsigned int *bt_vol)
54 {
55         /* Convert system gain to BT
56                 BT volume range : 0 ~ 127
57                 system volume range : 0 ~ 150 */
58
59         *bt_vol = 127 * ((float)sys_vol / 150);
60
61         /* volume table
62                 system volume : 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150
63                 avrcp  volume : 0  9 17 26 34 43 51 60 68 77  85  94 102 111 119 127 */
64
65         if (*bt_vol > 0 && *bt_vol < 127)
66                 *bt_vol = *bt_vol + 1;
67
68 #ifdef AVC_DEBUG
69         BT_DBG("System volume [%d], BT volume [%d]", sys_vol, *bt_vol);
70 #endif
71 }
72
73 static void __bt_audio_covert_bt_to_system_volume(unsigned int bt_vol, unsigned int *sys_vol)
74 {
75         /* Convert BT gain to system
76                 BT volume range : 0 ~ 127
77                 system volume range : 0 ~ 150 */
78
79         *sys_vol = 150 * ((float)bt_vol / 127);
80
81         /* volume table
82                 system volume : 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150
83                 avrcp  volume : 0  9 17 26 34 43 51 60 68 77  85  94 102 111 119 127 */
84
85         if (*sys_vol > 0 && *sys_vol < 150)
86                 *sys_vol = *sys_vol + 1;
87
88 #ifdef AVC_DEBUG
89         BT_DBG("System volume [%d], BT volume [%d]", *sys_vol, bt_vol);
90 #endif
91 }
92
93 static int __bt_audio_get_active_headset_volume(void)
94 {
95         int result = BLUETOOTH_ERROR_NONE;
96         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
97         bluetooth_device_address_t device_address;
98         gboolean connected = FALSE;
99         unsigned int volume = BT_VOLUME_MAX + 1;
100
101 #ifdef AVC_DEBUG
102         BT_DBG("+");
103 #endif
104
105         /* 1. Get active A2DP headset path */
106
107         /* We should modify this function to get the active headset in later */
108         connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
109
110         if (connected == FALSE) {
111                 BT_DBG("There is no active A2DP headset");
112                 return -1;
113         }
114
115         _bt_convert_addr_string_to_type(device_address.addr, connected_address);
116
117         /* 2. Get volume info for active transport for the path */
118         result = _bt_avrcp_target_get_volume(&device_address, &volume);
119         if (result != BLUETOOTH_ERROR_NONE) {
120                 BT_ERR("Fail to notify BT volume to headset");
121                 return -1;
122         }
123
124         if (volume > BT_VOLUME_MAX) {
125                 BT_DBG("Absolute Volume is not set in transport");
126                 return -1;
127         }
128
129         return volume;
130 }
131
132 /* Emit AVC mode changed signal (AVC_OFF/AVC_NULL/AVC_MAX) to application (Pulseaudio) */
133 static void __bt_audio_notify_avc_mode_changed(unsigned int avc_mode)
134 {
135         GVariant *param = g_variant_new("(u)", avc_mode);
136
137         /* AVC Event */
138         _bt_send_event(BT_AUDIO_AVC_EVENT,
139                         BLUETOOTH_EVENT_AUDIO_AVC_MODE_CHANGED,
140                         param);
141 }
142
143 /* Emit On / off state changed signal to application (Setting) */
144 static void __bt_audio_notify_avc_onoff_changed(bool status)
145 {
146         GVariant *param = g_variant_new("(b)", status);
147
148         /* HEADSET Event */
149         _bt_send_event(BT_HEADSET_EVENT,
150                         BLUETOOTH_EVENT_AUDIO_AVC_MODE_CHANGED,
151                         param);
152 }
153
154 static void __bt_audio_set_avc_mode(unsigned int mode)
155 {
156         unsigned int prev_mode = avc_mode;
157         bool onoff_state = false;
158
159         if (prev_mode == mode) {
160                 BT_DBG("No avc mode change");
161                 return;
162         }
163
164         BT_DBG("Previous mode [%d], New mode [%d]", prev_mode, mode);
165
166         /*  Emit AVC mode changed signal (AVC_OFF/AVC_NULL/AVC_MAX) to Pulseaudio  */
167         __bt_audio_notify_avc_mode_changed(mode);
168
169         avc_mode = mode;
170
171         switch (mode) {
172         case BT_AVC_OFF:
173                 onoff_state = false;
174                 break;
175         case BT_AVC_NULL:
176         case BT_AVC_MAX:
177                 if (prev_mode != BT_AVC_OFF) {
178                         BT_DBG("Don't need to send onff state changed");
179                         return;
180                 }
181
182                 onoff_state = true;
183                 break;
184         default:
185                 BT_ERR("Abnormal state!");
186                 return;
187                 break;
188         }
189
190         /* Emit On / off state changed signal to application (Setting) */
191         __bt_audio_notify_avc_onoff_changed(onoff_state);
192 }
193
194 static void __bt_audio_sync_absolute_volume(unsigned int bt_vol)
195 {
196         unsigned int sys_vol = 0;
197
198         BT_DBG("synchronize the system and bt volume");
199
200         __bt_audio_covert_bt_to_system_volume(bt_vol, &sys_vol);
201
202         bt_volume = bt_vol;
203         absolute_volume = sys_vol;
204 }
205
206 static void __bt_audio_set_user_avc_value(bool mode)
207 {
208         int volume = 0;
209
210         BT_DBG("mode: %d", mode);
211
212         if (mode == false) {
213                 __bt_audio_set_avc_mode(BT_AVC_OFF);
214                 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
215                 bt_volume = BT_VOLUME_MAX + 1;
216                 return;
217         }
218
219         if (avc_mode != BT_AVC_OFF) {
220                 BT_DBG("Already activate AVC mode");
221                 return;
222         }
223
224         volume = __bt_audio_get_active_headset_volume();
225
226         if (volume == -1) {
227                 __bt_audio_set_avc_mode(BT_AVC_OFF);
228                 return;
229         }
230
231         BT_INFO("The current transport supports AVC : volume [%d]", volume);
232
233         if (volume == 0) {
234                 __bt_audio_set_avc_mode(BT_AVC_NULL);
235         } else {
236                 BT_DBG("BT volume: %d", volume);
237                 __bt_audio_set_avc_mode(BT_AVC_MAX);
238         }
239
240         __bt_audio_sync_absolute_volume(volume);
241 }
242
243 static void __bt_audio_user_avc_mode_cb(keynode_t *node, void *data)
244 {
245         int type;
246         bool mode = VCONFKEY_BT_AVC_OFF;
247
248         DBG_SECURE("key=%s", vconf_keynode_get_name(node));
249         type = vconf_keynode_get_type(node);
250
251         if (type == VCONF_TYPE_BOOL) {
252                 mode = vconf_keynode_get_bool(node);
253                 __bt_audio_set_user_avc_value(mode);
254         } else {
255                 BT_ERR("Invaild vconf key type : %d", type);
256         }
257 }
258
259 int _bt_audio_init_absolute_volume_control(void)
260 {
261 #ifdef AVC_DEBUG
262         BT_DBG("+");
263 #endif
264
265         absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
266         bt_volume = BT_VOLUME_MAX + 1;
267         avc_mode = BT_AVC_OFF;
268
269         if (vconf_notify_key_changed(VCONFKEY_BT_AVC_MODE,
270                 (vconf_callback_fn)__bt_audio_user_avc_mode_cb, NULL) < 0) {
271                         BT_ERR("Unable to register key handler");
272                         return BLUETOOTH_ERROR_INTERNAL;
273         }
274
275         return BLUETOOTH_ERROR_NONE;
276 }
277
278 void _bt_audio_deinit_absolute_volume_control(void)
279 {
280 #ifdef AVC_DEBUG
281         BT_DBG("+");
282 #endif
283
284         absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
285         bt_volume = BT_VOLUME_MAX + 1;
286         avc_mode = BT_AVC_OFF;
287
288         vconf_ignore_key_changed(VCONFKEY_BT_AVC_MODE,
289                         (vconf_callback_fn)__bt_audio_user_avc_mode_cb);
290 }
291
292 int _bt_audio_set_absolute_volume(unsigned int volume)
293 {
294         int result = BLUETOOTH_ERROR_NONE;
295         unsigned int bt_vol = 0;
296         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
297         bluetooth_device_address_t device_address;
298         gboolean connected = FALSE;
299
300         BT_DBG("volume: %d", volume);
301
302         if (volume > 150) {
303                 BT_ERR("The volume exceeded 150");
304                 return BLUETOOTH_ERROR_INVALID_PARAM;
305         }
306
307         if (avc_mode == BT_AVC_OFF) {
308                 BT_ERR("AVC mode is off");
309                 return BLUETOOTH_ERROR_INTERNAL;
310         }
311
312         /* We should modify this function to get the active headset in later */
313         connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
314
315         if (connected == FALSE) {
316                 BT_DBG("There is no active A2DP headset");
317                 return BLUETOOTH_ERROR_NOT_CONNECTED;
318         }
319
320         _bt_convert_addr_string_to_type(device_address.addr, connected_address);
321
322         /* 1. Translate the absolute volume to bt volume */
323         __bt_audio_covert_system_to_bt_volume(volume, &bt_vol);
324
325         bt_volume = bt_vol;
326         absolute_volume = volume;
327
328         /* 2. Notify the bt_volume to transport (BT Headset) */
329         result = _bt_avrcp_target_notify_volume(&device_address, bt_volume);
330         if (result != BLUETOOTH_ERROR_NONE)
331                 BT_ERR("Fail to notify BT volume to headset");
332
333         /* 3. Notify the avc mode to the pulseaudio if it is needed */
334         if (volume == 0) {
335                 __bt_audio_set_avc_mode(BT_AVC_NULL);
336         } else {
337                 BT_DBG("System volume: %d", volume);
338                 __bt_audio_set_avc_mode(BT_AVC_MAX);
339         }
340
341         return result;
342 }
343
344 /* Just return the absolute_volume value */
345 int _bt_audio_get_absolute_volume(unsigned int *volume)
346 {
347         if (avc_mode == BT_AVC_OFF) {
348                 BT_ERR("AVC mode is off");
349                 return BLUETOOTH_ERROR_INTERNAL;
350         }
351
352         if (absolute_volume > ABSOLUTE_VOLUME_MAX) {
353                 BT_ERR("Absolute Volume level is not set");
354                 return BLUETOOTH_ERROR_INTERNAL;
355         }
356
357         *volume = absolute_volume;
358
359 #ifdef AVC_DEBUG
360         BT_DBG("volume: %d", *volume);
361 #endif
362
363         return BLUETOOTH_ERROR_NONE;
364 }
365
366 int _bt_audio_is_avc_activated(bool *activated)
367 {
368         unsigned int mode = BT_AVC_OFF;
369
370         if (_bt_audio_get_avc_mode(&mode) != BLUETOOTH_ERROR_NONE)
371                 BT_ERR("Fail to get the avc mode");
372
373         *activated = (mode == BT_AVC_OFF) ? false : true;
374
375 #ifdef AVC_DEBUG
376         BT_DBG("avc_mode: %d", avc_mode);
377 #endif
378
379         return BLUETOOTH_ERROR_NONE;
380 }
381
382 int _bt_audio_get_avc_mode(unsigned int *mode)
383 {
384         int state = 0;
385         int volume = 0;
386
387 #ifdef AVC_DEBUG
388         BT_DBG("+");
389 #endif
390
391         /* 1. Get AVC mode in the vconf value */
392         if (vconf_get_bool(VCONFKEY_BT_AVC_MODE, &state) != 0) {
393                 BT_ERR("vconf_get_bool failed");
394                 *mode = BT_AVC_OFF;
395                 return BLUETOOTH_ERROR_INTERNAL;
396         }
397
398         if (state == VCONFKEY_BT_AVC_OFF) {
399                 *mode = BT_AVC_OFF;
400                 return BLUETOOTH_ERROR_NONE;
401         }
402
403         volume = __bt_audio_get_active_headset_volume();
404
405         if (volume == -1) {
406                 *mode = BT_AVC_OFF;
407                 return BLUETOOTH_ERROR_NONE;
408         }
409
410         BT_INFO("The current transport supports AVC : volume [%d]", volume);
411
412         if (volume == 0) {
413                 *mode = BT_AVC_NULL;
414         } else {
415                 BT_DBG("BT volume: %d", volume);
416                 *mode = BT_AVC_MAX;
417         }
418
419         __bt_audio_sync_absolute_volume(volume);
420
421         return BLUETOOTH_ERROR_NONE;
422 }
423
424 void _bt_audio_handle_adapter_disabled(void)
425 {
426         BT_DBG("Reset AVC mode, and volume");
427
428         absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
429         bt_volume = BT_VOLUME_MAX + 1;
430         __bt_audio_set_avc_mode(BT_AVC_OFF);
431         return;
432 }
433
434 void _bt_audio_handle_a2dp_state_changed(const char *address, bool connected)
435 {
436         unsigned int mode = 0;
437
438 #ifdef AVC_DEBUG
439         BT_DBG("+");
440 #endif
441
442         /* In later, we can check the event for the active headset or not in here */
443
444         if (connected == false) {
445                 BT_DBG("Reset AVC mode, and volume");
446
447                 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
448                 bt_volume = BT_VOLUME_MAX + 1;
449                 __bt_audio_set_avc_mode(BT_AVC_OFF);
450                 return;
451         }
452
453         if (_bt_audio_get_avc_mode(&mode) != BLUETOOTH_ERROR_NONE) {
454                 BT_ERR("Fail to get the avc mode");
455                 return;
456         }
457
458         if (mode != BT_AVC_OFF) {
459                 __bt_audio_set_avc_mode(mode);
460
461                 /* Send the initial volume to application */
462                 _bt_send_event(BT_HEADSET_EVENT,
463                         BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED,
464                         g_variant_new("(u)", absolute_volume));
465         }
466 }
467
468 void _bt_audio_handle_transport_volume_changed(unsigned int bt_vol)
469 {
470         unsigned int sys_vol = 0;
471         int mode = BT_AVC_OFF;
472         unsigned int prev_vol = absolute_volume;
473
474 #ifdef AVC_DEBUG
475         BT_DBG("+");
476 #endif
477
478         if (bt_vol > BT_VOLUME_MAX) {
479                 /* BT AVC mode off, because bluez transport initiate the volue as MAX */
480                 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
481                 bt_volume = BT_VOLUME_MAX + 1;
482                 __bt_audio_set_avc_mode(BT_AVC_OFF);
483                 return;
484         }
485
486         __bt_audio_covert_bt_to_system_volume(bt_vol, &sys_vol);
487
488         bt_volume = bt_vol;
489         absolute_volume = sys_vol;
490
491         mode = (absolute_volume == 0) ? BT_AVC_NULL : BT_AVC_MAX;
492
493         __bt_audio_set_avc_mode(mode);
494
495         if (prev_vol == absolute_volume) {
496                 BT_DBG("Same volume level");
497                 return;
498         }
499
500         _bt_send_event(BT_HEADSET_EVENT,
501                 BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED,
502                 g_variant_new("(u)", absolute_volume));
503 }
504