Fix aarch64 casting build warnings
[platform/core/multimedia/libmm-sound.git] / mm_sound_client.c
index 3cbdf91..9b60ee6 100644 (file)
@@ -26,6 +26,7 @@
 #include <glib.h>
 #include <mm_error.h>
 #include <mm_debug.h>
+#include <vconf.h>
 
 #include "include/mm_sound.h"
 #include "include/mm_sound_client.h"
 #define CLIENT_HANDLE_MAX 256
 #define VOLUME_TYPE_LEN 64
 
+#define VCONF_KEY_VOLUME_PREFIX                                "file/private/sound/volume"
+#define VCONF_KEY_VOLUME_TYPE_SYSTEM           VCONF_KEY_VOLUME_PREFIX"/system"
+#define VCONF_KEY_VOLUME_TYPE_NOTIFICATION     VCONF_KEY_VOLUME_PREFIX"/notification"
+#define VCONF_KEY_VOLUME_TYPE_ALARM                    VCONF_KEY_VOLUME_PREFIX"/alarm"
+#define VCONF_KEY_VOLUME_TYPE_RINGTONE         VCONF_KEY_VOLUME_PREFIX"/ringtone"
+#define VCONF_KEY_VOLUME_TYPE_MEDIA                    VCONF_KEY_VOLUME_PREFIX"/media"
+#define VCONF_KEY_VOLUME_TYPE_CALL                     VCONF_KEY_VOLUME_PREFIX"/call"
+#define VCONF_KEY_VOLUME_TYPE_VOIP                     VCONF_KEY_VOLUME_PREFIX"/voip"
+#define VCONF_KEY_VOLUME_TYPE_VOICE            VCONF_KEY_VOLUME_PREFIX"/voice"
+#define VCONF_KEY_VOLUME_TYPE_ANDROID          VCONF_KEY_VOLUME_PREFIX"/fixed"
+
+#define VCONF_KEY_MUTE_PREFIX                          "file/private/sound/mute"
+#define VCONF_KEY_MUTE_TYPE_SYSTEM             VCONF_KEY_MUTE_PREFIX"/system"
+#define VCONF_KEY_MUTE_TYPE_NOTIFICATION       VCONF_KEY_MUTE_PREFIX"/notification"
+#define VCONF_KEY_MUTE_TYPE_ALARM                      VCONF_KEY_MUTE_PREFIX"/alarm"
+#define VCONF_KEY_MUTE_TYPE_RINGTONE           VCONF_KEY_MUTE_PREFIX"/ringtone"
+#define VCONF_KEY_MUTE_TYPE_MEDIA                      VCONF_KEY_MUTE_PREFIX"/media"
+#define VCONF_KEY_MUTE_TYPE_CALL                       VCONF_KEY_MUTE_PREFIX"/call"
+#define VCONF_KEY_MUTE_TYPE_VOIP                       VCONF_KEY_MUTE_PREFIX"/voip"
+#define VCONF_KEY_MUTE_TYPE_VOICE              VCONF_KEY_MUTE_PREFIX"/voice"
+
+/* For internal use */
+#define VCONF_KEY_VOLUME_TYPE_BIXBY            VCONF_KEY_VOLUME_PREFIX"/bixby"
+
+static char *g_volume_vconf[VOLUME_TYPE_MAX] = {
+       VCONF_KEY_VOLUME_TYPE_SYSTEM,           /* VOLUME_TYPE_SYSTEM */
+       VCONF_KEY_VOLUME_TYPE_NOTIFICATION,     /* VOLUME_TYPE_NOTIFICATION */
+       VCONF_KEY_VOLUME_TYPE_ALARM,            /* VOLUME_TYPE_ALARM */
+       VCONF_KEY_VOLUME_TYPE_RINGTONE,         /* VOLUME_TYPE_RINGTONE */
+       VCONF_KEY_VOLUME_TYPE_MEDIA,            /* VOLUME_TYPE_MEDIA */
+       VCONF_KEY_VOLUME_TYPE_CALL,                     /* VOLUME_TYPE_CALL */
+       VCONF_KEY_VOLUME_TYPE_VOIP,                     /* VOLUME_TYPE_VOIP */
+       VCONF_KEY_VOLUME_TYPE_VOICE,            /* VOLUME_TYPE_VOICE */
+       VCONF_KEY_VOLUME_TYPE_ANDROID           /* VOLUME_TYPE_FIXED */
+};
+
+static char *g_volume_vconf_internal[] = {
+       VCONF_KEY_VOLUME_TYPE_BIXBY,            /* VOLUME_TYPE_BIXBY */
+};
+
+static char *g_mute_vconf[] = {
+       VCONF_KEY_MUTE_TYPE_SYSTEM,             /* MUTE_TYPE_SYSTEM */
+       VCONF_KEY_MUTE_TYPE_NOTIFICATION,       /* MUTE_TYPE_NOTIFICATION */
+       VCONF_KEY_MUTE_TYPE_ALARM,              /* MUTE_TYPE_ALARM */
+       VCONF_KEY_MUTE_TYPE_RINGTONE,           /* MUTE_TYPE_RINGTONE */
+       VCONF_KEY_MUTE_TYPE_MEDIA,              /* MUTE_TYPE_MEDIA */
+       VCONF_KEY_MUTE_TYPE_CALL,                       /* MUTE_TYPE_CALL */
+       VCONF_KEY_MUTE_TYPE_VOIP,                       /* MUTE_TYPE_VOIP */
+       VCONF_KEY_MUTE_TYPE_VOICE,              /* MUTE_TYPE_VOICE */
+};
+
 struct callback_data {
        void *user_cb;
        void *user_data;
@@ -47,7 +99,11 @@ struct callback_data {
 
 #define GET_CB_DATA(_cb_data, _func, _userdata, _extradata) \
        do { \
-               _cb_data = (struct callback_data*) g_malloc0(sizeof(struct callback_data)); \
+               _cb_data = (struct callback_data*) g_try_malloc0(sizeof(struct callback_data)); \
+               if (!_cb_data) { \
+                       debug_error("failed to allocate callback_data"); \
+                       return MM_ERROR_OUT_OF_MEMORY; \
+               } \
                _cb_data->user_cb = _func; \
                _cb_data->user_data = _userdata; \
                _cb_data->extra_data = _extradata; \
@@ -55,7 +111,7 @@ struct callback_data {
 
 static pthread_mutex_t g_index_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t g_event_mutex = PTHREAD_MUTEX_INITIALIZER;
-guint g_idle_event_src;
+static guint g_idle_event_src;
 
 typedef struct {
        /* handle to watch end of playing */
@@ -139,99 +195,6 @@ void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_t
 /*****************************************************************************************
                            DBUS SUPPORTED FUNCTIONS
 ******************************************************************************************/
-int mm_sound_client_play_tone_with_stream_info(int tone, char *stream_type, int stream_id,
-                                                                                       double volume, int duration, int *handle)
-{
-       int ret = MM_ERROR_NONE;
-
-       debug_fenter();
-
-       ret = mm_sound_proxy_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle);
-
-       debug_fleave();
-       return ret;
-}
-
-static void _mm_sound_stop_callback_wrapper_func(int ended_handle, void *userdata)
-{
-       struct callback_data *cb_data = (struct callback_data*) userdata;
-       play_sound_end_callback_data_t *end_cb_data;
-
-       debug_log("ended_handle : %d", ended_handle);
-
-       if (cb_data == NULL) {
-               debug_warning("stop callback data null");
-               return;
-       }
-
-       end_cb_data = (play_sound_end_callback_data_t*) cb_data->extra_data;
-
-       if (ended_handle == end_cb_data->watching_handle) {
-               debug_log("Interested playing handle end : %d", ended_handle);
-               ((mm_sound_stop_callback_func)(cb_data->user_cb))(cb_data->user_data, ended_handle);
-               if (mm_sound_proxy_remove_play_sound_end_callback(end_cb_data->subs_id) != MM_ERROR_NONE)
-                       debug_error("mm_sound_client_dbus_remove_play_file_end_callback failed");
-       } else {
-               debug_log("Not interested playing handle : %d", ended_handle);
-       }
-}
-
-static void play_end_callback_data_free_func(void *data)
-{
-       struct callback_data *cb_data = (struct callback_data*) data;
-
-       if (cb_data) {
-               g_free(cb_data->extra_data);
-               g_free(cb_data);
-       }
-}
-
-int mm_sound_client_play_sound_with_stream_info(MMSoundPlayParam *param, int *handle, char* stream_type, int stream_id)
-{
-       int ret = MM_ERROR_NONE;
-       struct callback_data *cb_data = NULL;
-       play_sound_end_callback_data_t *end_cb_data;
-
-       ret = mm_sound_proxy_play_sound_with_stream_info(param->filename, param->loop, param->volume,
-                                                                                                       getpid(), handle, stream_type, stream_id);
-       if (ret != MM_ERROR_NONE) {
-               debug_error("Play Sound Failed");
-               goto failed;
-       }
-       if (param->callback) {
-               end_cb_data = (play_sound_end_callback_data_t *) g_malloc0(sizeof(play_sound_end_callback_data_t));
-               end_cb_data->watching_handle = *handle;
-               GET_CB_DATA(cb_data, param->callback, param->data, end_cb_data);
-
-               ret = mm_sound_proxy_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data,
-                                                                                                               play_end_callback_data_free_func, &end_cb_data->subs_id);
-               if (ret != MM_ERROR_NONE)
-                       debug_error("Add callback for play sound(%d) Failed", *handle);
-       }
-
-failed:
-
-       debug_fleave();
-       return ret;
-
-}
-
-int mm_sound_client_stop_sound(int handle)
-{
-       int ret = MM_ERROR_NONE;
-       debug_fenter();
-
-       if (handle < 0 || handle > CLIENT_HANDLE_MAX) {
-               ret = MM_ERROR_INVALID_ARGUMENT;
-               return ret;
-       }
-
-       ret = mm_sound_proxy_stop_sound(handle);
-
-       debug_fleave();
-       return ret;
-}
-
 static int _mm_sound_client_device_list_dump(GList *device_list)
 {
        int ret = MM_ERROR_NONE;
@@ -411,7 +374,7 @@ static void _mm_sound_device_connected_callback_wrapper_func(int device_id, cons
                return;
        }
 
-       device_flags = (int) cb_data->extra_data;
+       device_flags = (int)(uintptr_t)cb_data->extra_data;
        if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
                return;
 
@@ -432,7 +395,7 @@ int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_dev
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, (void*) device_flags);
+       GET_CB_DATA(cb_data, func, userdata, (void*)(uintptr_t)device_flags);
 
        ret = mm_sound_proxy_add_device_connected_callback(_mm_sound_device_connected_callback_wrapper_func,
                                                                                                        cb_data, g_free, subs_id);
@@ -469,7 +432,7 @@ static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, c
                return;
        }
 
-       device_flags = (int) cb_data->extra_data;
+       device_flags = (int)(uintptr_t)cb_data->extra_data;
        if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
                return;
 
@@ -490,7 +453,7 @@ int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
+       GET_CB_DATA(cb_data, func, userdata, (void *)(uintptr_t)device_flags);
 
        ret = mm_sound_proxy_add_device_info_changed_callback(_mm_sound_device_info_changed_callback_wrapper_func,
                                                                                                                cb_data, g_free, subs_id);
@@ -527,7 +490,7 @@ static void _mm_sound_device_state_changed_callback_wrapper_func(int device_id,
                return;
        }
 
-       device_flags = (int) cb_data->extra_data;
+       device_flags = (int)(uintptr_t)cb_data->extra_data;
 
        if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
                return;
@@ -549,7 +512,7 @@ int mm_sound_client_add_device_state_changed_callback(int device_flags, mm_sound
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
+       GET_CB_DATA(cb_data, func, userdata, (void *)(uintptr_t)device_flags);
 
        ret = mm_sound_proxy_add_device_state_changed_callback(_mm_sound_device_state_changed_callback_wrapper_func,
                                                                                                                cb_data, g_free, id);
@@ -585,7 +548,7 @@ static void _mm_sound_device_running_changed_callback_wrapper_func(int device_id
                return;
        }
 
-       device_flags = (int) cb_data->extra_data;
+       device_flags = (int)(uintptr_t)cb_data->extra_data;
 
        if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
                return;
@@ -607,7 +570,7 @@ int mm_sound_client_add_device_running_changed_callback(int device_flags, mm_sou
 
        debug_fenter();
 
-       GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
+       GET_CB_DATA(cb_data, func, userdata, (void *)(uintptr_t)device_flags);
 
        ret = mm_sound_proxy_add_device_running_changed_callback(_mm_sound_device_running_changed_callback_wrapper_func,
                                                                                                                        cb_data, g_free, id);
@@ -648,7 +611,7 @@ failed:
        return ret;
 }
 
-int __convert_volume_type_to_str(int volume_type, char **volume_type_str)
+int __convert_volume_type_to_str(volume_type_t volume_type, char **volume_type_str)
 {
        int ret = MM_ERROR_NONE;
 
@@ -684,38 +647,64 @@ int __convert_volume_type_to_str(int volume_type, char **volume_type_str)
                debug_error("unexpected volume type [%d]", volume_type);
                return MM_ERROR_SOUND_INTERNAL;
        }
-       if (!strncmp(*volume_type_str, "", VOLUME_TYPE_LEN)) {
-               debug_error("could not find the volume_type[%d] in this switch case statement", volume_type);
-               ret = MM_ERROR_SOUND_INTERNAL;
-       } else {
-               debug_log("volume_type[%s]", *volume_type_str);
+       debug_log("volume_type[%s]", *volume_type_str);
+       return ret;
+}
+
+int __convert_volume_type_internal_to_str(volume_type_internal_t volume_type, char **volume_type_str)
+{
+       int ret = MM_ERROR_NONE;
+
+       if (!volume_type_str)
+               return MM_ERROR_COMMON_INVALID_ARGUMENT;
+
+       switch (volume_type) {
+       case VOLUME_TYPE_BIXBY:
+               *volume_type_str = "bixby";
+               break;
+       default:
+               debug_error("unexpected volume type [%d]", volume_type);
+               return MM_ERROR_SOUND_INTERNAL;
        }
+       debug_log("volume_type[%s]", *volume_type_str);
        return ret;
 }
 
-static int __convert_volume_type_to_int(const char *volume_type_str, volume_type_t *volume_type)
+static int __convert_volume_type_to_int(const char *volume_type_str, int *volume_type, bool *is_for_internal)
 {
        int ret = MM_ERROR_NONE;
 
-       if (!volume_type || !volume_type_str)
+       if (!volume_type || !volume_type_str || !is_for_internal)
                return MM_ERROR_COMMON_INVALID_ARGUMENT;
 
        if (!strncmp(volume_type_str, "system", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_SYSTEM;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "notification", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_NOTIFICATION;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "alarm", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_ALARM;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "ringtone", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_RINGTONE;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "media", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_MEDIA;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "call", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_CALL;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "voip", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_VOIP;
+               *is_for_internal = false;
        } else if (!strncmp(volume_type_str, "voice", VOLUME_TYPE_LEN)) {
                *volume_type = VOLUME_TYPE_VOICE;
+               *is_for_internal = false;
+       /* else-if statements below are for internal use */
+       } else if (!strncmp(volume_type_str, "bixby", VOLUME_TYPE_LEN)) {
+               *volume_type = VOLUME_TYPE_BIXBY;
+               *is_for_internal = true;
        } else {
                debug_log("Invalid volume type : [%s]", volume_type_str);
                ret = MM_ERROR_SOUND_INTERNAL;
@@ -724,28 +713,100 @@ static int __convert_volume_type_to_int(const char *volume_type_str, volume_type
        return ret;
 }
 
-int mm_sound_client_set_volume_by_type(const int volume_type, const unsigned int volume_level)
+int mm_sound_client_set_volume_by_type(volume_type_t type, const unsigned int level)
 {
        int ret = MM_ERROR_NONE;
        char *type_str = NULL;
        debug_fenter();
 
-       if ((ret = __convert_volume_type_to_str(volume_type, &type_str)) != MM_ERROR_NONE) {
+       if (type >= VOLUME_TYPE_MAX) {
+               debug_error("invalid volume type %d", type);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       if ((ret = __convert_volume_type_to_str(type, &type_str)) != MM_ERROR_NONE) {
                debug_error("volume type convert failed");
                goto failed;
        }
 
-       ret = mm_sound_proxy_set_volume_by_type(type_str, volume_level);
+       ret = mm_sound_proxy_set_volume_by_type(type_str, level);
 
 failed:
        debug_fleave();
        return ret;
 }
 
+int mm_sound_client_get_volume_by_type(volume_type_t type, unsigned int *level)
+{
+       int ret = MM_ERROR_NONE;
+       int vconf_value = 0;
+
+       if (level == NULL) {
+               debug_error("invalid argument, level is null");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       if (type >= VOLUME_TYPE_MAX) {
+               debug_error("invalid volume type %d", type);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       /* Get volume value from VCONF */
+       if (vconf_get_int(g_volume_vconf[type], &vconf_value)) {
+               debug_error("vconf_get_int(%s) failed..\n", g_volume_vconf[type]);
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       *level = vconf_value;
+
+       return ret;
+}
+
+int mm_sound_client_set_volume_by_internal_type(volume_type_internal_t type, const unsigned int level)
+{
+       int ret = MM_ERROR_NONE;
+       char *type_str = NULL;
+
+       debug_fenter();
+
+       if ((ret = __convert_volume_type_internal_to_str(type, &type_str)) != MM_ERROR_NONE) {
+               debug_error("volume type convert failed");
+               goto failed;
+       }
+
+       ret = mm_sound_proxy_set_volume_by_type(type_str, level);
+
+failed:
+       debug_fleave();
+       return ret;
+}
+
+int mm_sound_client_get_volume_by_internal_type(volume_type_internal_t type, unsigned int *level)
+{
+       int ret = MM_ERROR_NONE;
+       int vconf_value = 0;
+
+       if (level == NULL) {
+               debug_error("invalid argument, level is null");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       /* Get volume value from VCONF */
+       if (vconf_get_int(g_volume_vconf_internal[type], &vconf_value)) {
+               debug_error("vconf_get_int(%s) failed..\n", g_volume_vconf_internal[type]);
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       *level = vconf_value;
+
+       return ret;
+}
+
 static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction, const char *volume_type_str,
                                                                                                                int volume_level, void *userdata)
 {
-       volume_type_t volume_type = 0;
+       int volume_type = 0;
+       bool is_for_internal =  false;
        struct callback_data *cb_data = (struct callback_data *) userdata;
 
        debug_log("direction : %s, volume_type : %s, volume_level : %d",
@@ -756,13 +817,20 @@ static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction
                return;
        }
 
-       if (__convert_volume_type_to_int(volume_type_str, &volume_type) != MM_ERROR_NONE) {
+       if (__convert_volume_type_to_int(volume_type_str, &volume_type, &is_for_internal) != MM_ERROR_NONE) {
                debug_error("volume type convert failed");
                return;
        }
-       debug_log("Call volume changed user cb, direction : %s, vol_type : %s(%d), level : %u",
+
+       if (!is_for_internal && !cb_data->extra_data) {
+               debug_log("Invoke volume changed cb, direction : %s, vol_type : %s(%d), level : %u",
                        direction, volume_type_str, volume_type, volume_level);
-       ((mm_sound_volume_changed_cb)(cb_data->user_cb))(volume_type, volume_level, cb_data->user_data);
+               ((mm_sound_volume_changed_cb)(cb_data->user_cb))((volume_type_t)volume_type, volume_level, cb_data->user_data);
+       } else if (is_for_internal && (cb_data->extra_data && (bool)(cb_data->extra_data))) {
+               debug_log("Invoke internal volume changed cb, direction : %s, vol_type : %s(%d), level : %u",
+                       direction, volume_type_str, volume_type, volume_level);
+               ((mm_sound_volume_changed_cb_internal)(cb_data->user_cb))((volume_type_internal_t)volume_type, volume_level, cb_data->user_data);
+       }
 }
 
 int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* userdata, unsigned int *subs_id)
@@ -781,6 +849,23 @@ int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func,
        return ret;
 }
 
+int mm_sound_client_add_volume_changed_callback_internal(mm_sound_volume_changed_cb_internal func, void* userdata, unsigned int *subs_id)
+{
+       int ret = MM_ERROR_NONE;
+       struct callback_data *cb_data = NULL;
+       gboolean is_for_internal = true;
+
+       debug_fenter();
+
+       GET_CB_DATA(cb_data, func, userdata, (void*)(uintptr_t)is_for_internal);
+
+       ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id);
+
+       debug_fleave();
+
+       return ret;
+}
+
 int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id)
 {
        int ret = MM_ERROR_NONE;
@@ -792,6 +877,54 @@ int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id)
        return ret;
 }
 
+int mm_sound_client_set_mute_by_type(volume_type_t type, bool mute)
+{
+       int ret = MM_ERROR_NONE;
+       char *type_str = NULL;
+
+       debug_fenter();
+
+       if (type > VOLUME_TYPE_VOICE) {
+               debug_error("invalid volume type %d", type);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       if ((ret = __convert_volume_type_to_str(type, &type_str)) != MM_ERROR_NONE) {
+               debug_error("volume type convert failed");
+               goto failed;
+       }
+
+       ret = mm_sound_proxy_set_mute_by_type(type_str, mute);
+
+failed:
+       debug_fleave();
+       return ret;
+}
+
+int mm_sound_client_get_mute_by_type(volume_type_t type, bool *muted)
+{
+       int ret = MM_ERROR_NONE;
+       int vconf_value = 0;
+
+       debug_fenter();
+
+       if (type > VOLUME_TYPE_VOICE) {
+               debug_error("invalid volume type %d", type);
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       /* Get mute state from VCONF */
+       if (vconf_get_bool(g_mute_vconf[type], &vconf_value)) {
+               debug_error("vconf_get_int(%s) failed..\n", g_mute_vconf[type]);
+               return MM_ERROR_SOUND_INTERNAL;
+       }
+
+       *muted = (bool)vconf_value;
+
+       debug_fleave();
+       return ret;
+}
+
 int mm_sound_client_set_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_parameters, const char *filter_group)
 {
        int ret = MM_ERROR_NONE;
@@ -825,7 +958,7 @@ int mm_sound_client_control_filter_by_type(const char *stream_type, const char *
        return ret;
 }
 
-int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result)
+int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result, bool *is_for_watching)
 {
        int ret = MM_ERROR_NONE;
        int i = 0;
@@ -839,6 +972,14 @@ int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result)
                                continue;
                        if (g_focus_sound_handle[i].focus_cb_thread == mine) {
                                *result = true;
+                               if (is_for_watching)
+                                       *is_for_watching = false;
+                               break;
+                       }
+                       if (g_focus_sound_handle[i].focus_watch_cb_thread == mine) {
+                               *result = true;
+                               if (is_for_watching)
+                                       *is_for_watching = true;
                                break;
                        }
                }
@@ -869,7 +1010,7 @@ int mm_sound_client_register_focus(int pid, const char *stream_type,
        ret = mm_sound_proxy_register_focus(index, stream_type, id);
        if (ret == MM_ERROR_NONE) {
                debug_msg("Success to register focus, client_fd[%d], id[%d]", g_focus_sound_handle[index].client_fd, *id);
-               if (focus_init_context(index)) {
+               if (focus_init_context(index, false)) {
                        ret = MM_ERROR_SOUND_INTERNAL;
                        goto cleanup;
                }
@@ -878,10 +1019,11 @@ int mm_sound_client_register_focus(int pid, const char *stream_type,
                goto cleanup;
        }
 
+       g_mutex_init(&g_focus_sound_handle[index].focus_lock);
        focus_init_callback(index, false);
 
 cleanup:
-       if (ret)
+       if (ret != MM_ERROR_NONE && index >= 0)
                g_focus_sound_handle[index].is_used = false;
 
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
@@ -905,12 +1047,9 @@ int mm_sound_client_unregister_focus(int id)
                goto cleanup;
        }
 
-       if (!g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) {
-               debug_warning("maybe focus_callback is being called, try one more time..");
-               usleep(2500000); /* 2.5 sec */
-               if (g_mutex_trylock(&g_focus_sound_handle[index].focus_lock))
-                       debug_msg("finally got focus_lock");
-       }
+       g_mutex_lock(&g_focus_sound_handle[index].focus_lock);
+
+       g_focus_sound_handle[index].is_destroying = true;
 
        ret = mm_sound_proxy_unregister_focus(index);
        if (ret == MM_ERROR_NONE)
@@ -918,16 +1057,18 @@ int mm_sound_client_unregister_focus(int id)
        else
                debug_error("Error occurred : 0x%x", ret);
 
-       g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
-
        focus_deinit_callback(index, false);
        g_focus_sound_handle[index].focus_fd = 0;
        g_focus_sound_handle[index].focus_pid = 0;
        g_focus_sound_handle[index].client_fd = 0;
        g_focus_sound_handle[index].handle = 0;
        g_focus_sound_handle[index].is_used = false;
-       focus_deinit_context(index);
+       focus_deinit_context(index, false);
+
+       g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
+       g_mutex_clear(&g_focus_sound_handle[index].focus_lock);
 
+       g_focus_sound_handle[index].is_destroying = false;
 cleanup:
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
        debug_fleave();
@@ -951,7 +1092,7 @@ int mm_sound_client_set_focus_reacquisition(int id, bool reacquisition)
                goto cleanup;
        }
 
-       ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), &result);
+       ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), &result, NULL);
        if (ret) {
                debug_error("mm_sound_client_is_focus_cb_thread failed");
                goto cleanup;
@@ -1156,7 +1297,7 @@ int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focu
        if (ret == MM_ERROR_NONE) {
                *id = g_focus_sound_handle[index].handle;
                debug_msg("Success to add watch focus cb, id(%d)", *id);
-               if (focus_init_context(index)) {
+               if (focus_init_context(index, true)) {
                        ret = MM_ERROR_SOUND_INTERNAL;
                        goto cleanup;
                }
@@ -1168,7 +1309,7 @@ int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focu
        focus_init_callback(index, true);
 
 cleanup:
-       if (ret)
+       if (ret != MM_ERROR_NONE && index >= 0)
                g_focus_sound_handle[index].is_used = false;
 
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
@@ -1231,7 +1372,7 @@ int mm_sound_client_unset_focus_watch_callback(int id)
        g_focus_sound_handle[index].focus_pid = 0;
        g_focus_sound_handle[index].client_fd = 0;
        g_focus_sound_handle[index].handle = 0;
-       focus_deinit_context(index);
+       focus_deinit_context(index, true);
 
 cleanup:
        MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
@@ -1296,39 +1437,31 @@ int mm_sound_client_execute_focus_func_in_main_context(focus_idle_event_type_e t
        return MM_ERROR_NONE;
 }
 
-int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data, unsigned int *subs_id)
+int mm_sound_client_add_ducking_state_changed_callback(mm_sound_ducking_state_changed_cb func, void* userdata, unsigned int *subs_id)
 {
        int ret = MM_ERROR_NONE;
+       struct callback_data *cb_data = NULL;
 
        debug_fenter();
 
-       ret = mm_sound_proxy_add_test_callback(func, user_data, g_free, subs_id);
-
-       debug_fleave();
-       return ret;
-}
-
-int mm_sound_client_remove_test_callback(unsigned int subs_id)
-{
-       int ret = MM_ERROR_NONE;
-       debug_fenter();
+       GET_CB_DATA(cb_data, func, userdata, NULL);
 
-       ret = mm_sound_proxy_remove_test_callback(subs_id);
+       ret = mm_sound_proxy_add_ducking_state_changed_callback((mm_sound_ducking_state_changed_wrapper_cb)func,
+               cb_data, g_free, subs_id);
 
        debug_fleave();
+
        return ret;
 }
 
-int mm_sound_client_test(int a, int b, int* getv)
+int mm_sound_client_remove_ducking_state_changed_callback(unsigned int subs_id)
 {
        int ret = MM_ERROR_NONE;
-
        debug_fenter();
 
-       ret = mm_sound_proxy_test(a, b, getv);
-       debug_log("%d * %d -> result : %d", a, b, *getv);
+       ret = mm_sound_proxy_remove_ducking_state_changed_callback(subs_id);
 
        debug_fleave();
-
        return ret;
 }
+