*/
#include <vconf.h>
+#include <vconf-internal-keys.h>
#include <oal-event.h>
#include <oal-hardware.h>
#include "bt-service-audio-common.h"
#include "bt-service-event.h"
-static unsigned int absolute_volume = 0;
-static unsigned int bt_volume = 0;
+/* Avoid the build error related to vconf.h's dependency */
+#ifndef VCONFKEY_BT_AVC_MODE
+#define VCONFKEY_BT_AVC_MODE "db/bluetooth/avc_mode"
+#endif
+
+#ifndef VCONFKEY_BT_AVC_OFF
+#define VCONFKEY_BT_AVC_OFF false
+#endif
+
+#define ABSOLUTE_VOLUME_MAX 150
+#define BT_VOLUME_MAX 127
+
+static unsigned int absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
+static unsigned int bt_volume = BT_VOLUME_MAX + 1;
static unsigned int avc_mode = BT_AVC_OFF;
+static int __bt_audio_get_active_headset_volume(void)
+{
+ char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+ gboolean connected = FALSE;
+ int volume = -1;
+
+ /* 1. Get active A2DP headset path */
+
+ /* We should modify this function to get the active headset in later */
+ connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
+
+ if (connected == FALSE) {
+ BT_DBG("There is no active A2DP headset");
+ return -1;
+ }
+
+ /* 2. Get volume info for active transport for the path */
+
+ /*
+ _bt_avrcp_transport_get_property(VOLUME, &volume)
+ */
+
+ return volume;
+}
+
+static void __bt_audio_notify_avc_mode_changed(unsigned int avc_mode)
+{
+ GVariant *param = g_variant_new("(u)", avc_mode);
+
+ _bt_send_event(BT_AUDIO_AVC_EVENT,
+ BLUETOOTH_EVENT_AUDIO_AVC_MODE_CHANGED,
+ param);
+}
+
+static void __bt_audio_set_avc_mode(unsigned int mode)
+{
+ unsigned int prev_mode = avc_mode;
+
+ if (prev_mode == mode) {
+ BT_DBG("No avc mode change");
+ return;
+ }
+
+ BT_ERR("Previous mode [%d], New mode [%d]", prev_mode, mode);
+
+ __bt_audio_notify_avc_mode_changed(mode);
+
+ avc_mode = mode;
+}
+
+static void __bt_audio_set_user_avc_value(bool mode)
+{
+ int volume = 0;
+
+ if (mode == false) {
+ __bt_audio_set_avc_mode(BT_AVC_OFF);
+ return;
+ }
+
+ volume = __bt_audio_get_active_headset_volume();
+
+ if (volume == -1) {
+ __bt_audio_set_avc_mode(BT_AVC_OFF);
+ return;
+ }
+
+ BT_INFO("The current transport supports AVC : volume [%d]", volume);
+
+ if (volume == 0) {
+ __bt_audio_set_avc_mode(BT_AVC_NULL);
+ } else {
+ BT_DBG("BT volume: %d", volume);
+ __bt_audio_set_avc_mode(BT_AVC_MAX);
+ }
+
+ if (absolute_volume > ABSOLUTE_VOLUME_MAX || bt_volume > BT_VOLUME_MAX) {
+ BT_DBG("synchronize the system and bt volume");
+
+ /* Add Sync volumes */
+ }
+}
+
+static void __bt_audio_user_avc_mode_cb(keynode_t *node, void *data)
+{
+ int type;
+ bool mode = VCONFKEY_BT_AVC_OFF;
+
+ DBG_SECURE("key=%s", vconf_keynode_get_name(node));
+ type = vconf_keynode_get_type(node);
+
+ if (type == VCONF_TYPE_BOOL) {
+ mode = vconf_keynode_get_bool(node);
+ __bt_audio_set_user_avc_value(mode);
+ } else {
+ BT_ERR("Invaild vconf key type : %d", type);
+ }
+}
+
+int _bt_audio_init_absolute_volume_control(void)
+{
+ absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
+ bt_volume = BT_VOLUME_MAX + 1;
+ avc_mode = BT_AVC_OFF;
+
+ if (vconf_notify_key_changed(VCONFKEY_BT_AVC_MODE,
+ (vconf_callback_fn)__bt_audio_user_avc_mode_cb, NULL) < 0) {
+ BT_ERR("Unable to register key handler");
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
+ return BLUETOOTH_ERROR_NONE;
+}
+
+void _bt_audio_deinit_absolute_volume_control(void)
+{
+ absolute_volume = ABSOLUTE_VOLUME_MAX + 1;
+ bt_volume = BT_VOLUME_MAX + 1;
+ avc_mode = BT_AVC_OFF;
+
+ vconf_ignore_key_changed(VCONFKEY_BT_AVC_MODE,
+ (vconf_callback_fn)__bt_audio_user_avc_mode_cb);
+}
+
int _bt_audio_set_absolute_volume(unsigned int volume)
{
int result = BLUETOOTH_ERROR_NONE;
+ if (avc_mode == BT_AVC_OFF) {
+ BT_ERR("AVC mode is off");
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
/* 1. Translate the absolute volume to bt volume */
/* Convert system gain to BT
/* 2. Notify the bt_volume to transport (BT Headset) */
+ /*
+ _bt_avrcp_transport_set_property(VOLUME, bt_volume)
+ */
+
/* 3. Notify the avc mode to the pulseaudio if it is needed */
+ if (volume == 0) {
+ __bt_audio_set_avc_mode(BT_AVC_NULL);
+ } else {
+ BT_DBG("BT volume: %d", volume);
+ __bt_audio_set_avc_mode(BT_AVC_MAX);
+ }
return result;
}
{
int result = BLUETOOTH_ERROR_NONE;
+ if (avc_mode == BT_AVC_OFF) {
+ BT_ERR("AVC mode is off");
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+
*volume = absolute_volume;
return result;
int _bt_audio_is_avc_activated(bool *activated)
{
- *activated = (avc_mode == BT_AVC_OFF) ? false : true;
+ unsigned int mode = BT_AVC_OFF;
+
+ if (_bt_audio_get_avc_mode(&mode) != BLUETOOTH_ERROR_NONE)
+ BT_ERR("Fail to get the avc mode");
+
+ *activated = (mode == BT_AVC_OFF) ? false : true;
return BLUETOOTH_ERROR_NONE;
}
int _bt_audio_get_avc_mode(unsigned int *mode)
{
- /* 1. AVC mode in the vconf value */
+ int state = 0;
+ int volume = 0;
- /* 2. Get active A2DP headset path */
+ /* 1. Get AVC mode in the vconf value */
+ if (vconf_get_bool(VCONFKEY_BT_AVC_MODE, &state) != 0) {
+ BT_ERR("vconf_get_bool failed");
+ *mode = BT_AVC_OFF;
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
- /* 3. Get volume info for activae transport for the path */
+ if (state == VCONFKEY_BT_AVC_OFF) {
+ *mode = BT_AVC_OFF;
+ return BLUETOOTH_ERROR_NONE;
+ }
- *mode = avc_mode;
+ volume = __bt_audio_get_active_headset_volume();
- return BLUETOOTH_ERROR_NONE;
-}
+ if (volume == -1) {
+ *mode = BT_AVC_OFF;
+ return BLUETOOTH_ERROR_NONE;
+ }
-int _bt_audio_notify_avc_mode_changed(unsigned int avc_mode)
-{
- GVariant *param = g_variant_new("(u)", avc_mode);
+ BT_INFO("The current transport supports AVC : volume [%d]", volume);
- _bt_send_event(BT_AUDIO_AVC_EVENT,
- BLUETOOTH_EVENT_AUDIO_AVC_MODE_CHANGED,
- param);
+ if (volume == 0) {
+ *mode = BT_AVC_NULL;
+ } else {
+ BT_DBG("BT volume: %d", volume);
+ *mode = BT_AVC_MAX;
+ }
+
+ if (absolute_volume > ABSOLUTE_VOLUME_MAX || bt_volume > BT_VOLUME_MAX) {
+ BT_DBG("synchronize the system and bt volume");
+
+ /* Add Sync volumes */
+ }
return BLUETOOTH_ERROR_NONE;
}
-/* 1. When a2dp headset is connected, we should set 'AVC' mode into pulseaudio */
+/* 1. When a2dp headset is connected, we should set 'AVC' mode internaly */
/* 2. If the avc mode is changed, we should inform 'AVC' mode to pulseaudio */
/* 3. If BT is off, we should send 'AVC' off mode event for application */
/* 4. If BT A2DP is disconnected, we should send 'AVC' off mode event for application */