4 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Dohyun Pyun <dh79.pyun@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <vconf-internal-keys.h>
25 #include <oal-event.h>
26 #include <oal-hardware.h>
27 #include <oal-audio-src.h>
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"
34 /* We will remove this flag after stabilizing the functionality */
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"
42 #ifndef VCONFKEY_BT_AVC_OFF
43 #define VCONFKEY_BT_AVC_OFF false
46 #define ABSOLUTE_VOLUME_MAX 150
47 #define BT_VOLUME_MAX 127
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;
53 static void __bt_audio_covert_system_to_bt_volume(unsigned int sys_vol, unsigned int *bt_vol)
55 /* Convert system gain to BT
56 BT volume range : 0 ~ 127
57 system volume range : 0 ~ 150 */
59 *bt_vol = 127 * ((float)sys_vol / 150);
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 */
65 if (*bt_vol > 0 && *bt_vol < 127)
66 *bt_vol = *bt_vol + 1;
69 BT_DBG("System volume [%d], BT volume [%d]", sys_vol, *bt_vol);
73 static void __bt_audio_covert_bt_to_system_volume(unsigned int bt_vol, unsigned int *sys_vol)
75 /* Convert BT gain to system
76 BT volume range : 0 ~ 127
77 system volume range : 0 ~ 150 */
79 *sys_vol = 150 * ((float)bt_vol / 127);
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 */
85 if (*sys_vol > 0 && *sys_vol < 150)
86 *sys_vol = *sys_vol + 1;
89 BT_DBG("System volume [%d], BT volume [%d]", *sys_vol, bt_vol);
93 static int __bt_audio_get_active_headset_volume(void)
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;
105 /* 1. Get active A2DP headset path */
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);
110 if (connected == FALSE) {
111 BT_DBG("There is no active A2DP headset");
115 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
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");
124 if (volume > BT_VOLUME_MAX) {
125 BT_DBG("Absolute Volume is not set in transport");
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)
135 GVariant *param = g_variant_new("(u)", avc_mode);
138 _bt_send_event(BT_AUDIO_AVC_EVENT,
139 BLUETOOTH_EVENT_AUDIO_AVC_MODE_CHANGED,
143 /* Emit On / off state changed signal to application (Setting) */
144 static void __bt_audio_notify_avc_onoff_changed(bool status)
146 GVariant *param = g_variant_new("(b)", status);
149 _bt_send_event(BT_HEADSET_EVENT,
150 BLUETOOTH_EVENT_AUDIO_AVC_MODE_CHANGED,
154 static void __bt_audio_set_avc_mode(unsigned int mode)
156 unsigned int prev_mode = avc_mode;
157 bool onoff_state = false;
159 if (prev_mode == mode) {
160 BT_DBG("No avc mode change");
164 BT_DBG("Previous mode [%d], New mode [%d]", prev_mode, mode);
166 /* Emit AVC mode changed signal (AVC_OFF/AVC_NULL/AVC_MAX) to Pulseaudio */
167 __bt_audio_notify_avc_mode_changed(mode);
177 if (prev_mode != BT_AVC_OFF) {
178 BT_DBG("Don't need to send onff state changed");
185 BT_ERR("Abnormal state!");
190 /* Emit On / off state changed signal to application (Setting) */
191 __bt_audio_notify_avc_onoff_changed(onoff_state);
194 static void __bt_audio_sync_absolute_volume(unsigned int bt_vol)
196 unsigned int sys_vol = 0;
198 BT_DBG("synchronize the system and bt volume");
200 __bt_audio_covert_bt_to_system_volume(bt_vol, &sys_vol);
203 absolute_volume = sys_vol;
206 static void __bt_audio_set_user_avc_value(bool mode)
210 BT_DBG("mode: %d", mode);
213 __bt_audio_set_avc_mode(BT_AVC_OFF);
214 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
215 bt_volume = BT_VOLUME_MAX + 1;
219 if (avc_mode != BT_AVC_OFF) {
220 BT_DBG("Already activate AVC mode");
224 volume = __bt_audio_get_active_headset_volume();
227 __bt_audio_set_avc_mode(BT_AVC_OFF);
231 BT_INFO("The current transport supports AVC : volume [%d]", volume);
234 __bt_audio_set_avc_mode(BT_AVC_NULL);
236 BT_DBG("BT volume: %d", volume);
237 __bt_audio_set_avc_mode(BT_AVC_MAX);
240 __bt_audio_sync_absolute_volume(volume);
243 static void __bt_audio_user_avc_mode_cb(keynode_t *node, void *data)
246 bool mode = VCONFKEY_BT_AVC_OFF;
248 DBG_SECURE("key=%s", vconf_keynode_get_name(node));
249 type = vconf_keynode_get_type(node);
251 if (type == VCONF_TYPE_BOOL) {
252 mode = vconf_keynode_get_bool(node);
253 __bt_audio_set_user_avc_value(mode);
255 BT_ERR("Invaild vconf key type : %d", type);
259 int _bt_audio_init_absolute_volume_control(void)
265 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
266 bt_volume = BT_VOLUME_MAX + 1;
267 avc_mode = BT_AVC_OFF;
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;
275 return BLUETOOTH_ERROR_NONE;
278 void _bt_audio_deinit_absolute_volume_control(void)
284 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
285 bt_volume = BT_VOLUME_MAX + 1;
286 avc_mode = BT_AVC_OFF;
288 vconf_ignore_key_changed(VCONFKEY_BT_AVC_MODE,
289 (vconf_callback_fn)__bt_audio_user_avc_mode_cb);
292 int _bt_audio_set_absolute_volume(unsigned int volume)
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;
300 BT_DBG("volume: %d", volume);
303 BT_ERR("The volume exceeded 150");
304 return BLUETOOTH_ERROR_INVALID_PARAM;
307 if (avc_mode == BT_AVC_OFF) {
308 BT_ERR("AVC mode is off");
309 return BLUETOOTH_ERROR_INTERNAL;
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);
315 if (connected == FALSE) {
316 BT_DBG("There is no active A2DP headset");
317 return BLUETOOTH_ERROR_NOT_CONNECTED;
320 _bt_convert_addr_string_to_type(device_address.addr, connected_address);
322 /* 1. Translate the absolute volume to bt volume */
323 __bt_audio_covert_system_to_bt_volume(volume, &bt_vol);
326 absolute_volume = volume;
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");
333 /* 3. Notify the avc mode to the pulseaudio if it is needed */
335 __bt_audio_set_avc_mode(BT_AVC_NULL);
337 BT_DBG("System volume: %d", volume);
338 __bt_audio_set_avc_mode(BT_AVC_MAX);
344 /* Just return the absolute_volume value */
345 int _bt_audio_get_absolute_volume(unsigned int *volume)
347 if (avc_mode == BT_AVC_OFF) {
348 BT_ERR("AVC mode is off");
349 return BLUETOOTH_ERROR_INTERNAL;
352 if (absolute_volume > ABSOLUTE_VOLUME_MAX) {
353 BT_ERR("Absolute Volume level is not set");
354 return BLUETOOTH_ERROR_INTERNAL;
357 *volume = absolute_volume;
360 BT_DBG("volume: %d", *volume);
363 return BLUETOOTH_ERROR_NONE;
366 int _bt_audio_is_avc_activated(bool *activated)
368 unsigned int mode = BT_AVC_OFF;
370 if (_bt_audio_get_avc_mode(&mode) != BLUETOOTH_ERROR_NONE)
371 BT_ERR("Fail to get the avc mode");
373 *activated = (mode == BT_AVC_OFF) ? false : true;
376 BT_DBG("avc_mode: %d", avc_mode);
379 return BLUETOOTH_ERROR_NONE;
382 int _bt_audio_get_avc_mode(unsigned int *mode)
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");
395 return BLUETOOTH_ERROR_INTERNAL;
398 if (state == VCONFKEY_BT_AVC_OFF) {
400 return BLUETOOTH_ERROR_NONE;
403 volume = __bt_audio_get_active_headset_volume();
407 return BLUETOOTH_ERROR_NONE;
410 BT_INFO("The current transport supports AVC : volume [%d]", volume);
415 BT_DBG("BT volume: %d", volume);
419 __bt_audio_sync_absolute_volume(volume);
421 return BLUETOOTH_ERROR_NONE;
424 void _bt_audio_handle_adapter_disabled(void)
426 BT_DBG("Reset AVC mode, and volume");
428 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
429 bt_volume = BT_VOLUME_MAX + 1;
430 __bt_audio_set_avc_mode(BT_AVC_OFF);
434 void _bt_audio_handle_a2dp_state_changed(const char *address, bool connected)
436 unsigned int mode = 0;
442 /* In later, we can check the event for the active headset or not in here */
444 if (connected == false) {
445 BT_DBG("Reset AVC mode, and volume");
447 absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
448 bt_volume = BT_VOLUME_MAX + 1;
449 __bt_audio_set_avc_mode(BT_AVC_OFF);
453 if (_bt_audio_get_avc_mode(&mode) != BLUETOOTH_ERROR_NONE) {
454 BT_ERR("Fail to get the avc mode");
458 if (mode != BT_AVC_OFF) {
459 __bt_audio_set_avc_mode(mode);
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));
468 void _bt_audio_handle_transport_volume_changed(unsigned int bt_vol)
470 unsigned int sys_vol = 0;
471 int mode = BT_AVC_OFF;
472 unsigned int prev_vol = absolute_volume;
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);
486 __bt_audio_covert_bt_to_system_volume(bt_vol, &sys_vol);
489 absolute_volume = sys_vol;
491 mode = (absolute_volume == 0) ? BT_AVC_NULL : BT_AVC_MAX;
493 __bt_audio_set_avc_mode(mode);
495 if (prev_vol == absolute_volume) {
496 BT_DBG("Same volume level");
500 _bt_send_event(BT_HEADSET_EVENT,
501 BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED,
502 g_variant_new("(u)", absolute_volume));