Add vc_mgr_ducking files 10/279310/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Fri, 5 Aug 2022 03:45:42 +0000 (12:45 +0900)
committersooyeon <sooyeon.kim@samsung.com>
Fri, 5 Aug 2022 08:53:44 +0000 (17:53 +0900)
This patch is cherry-picked from next commit:
https://review.tizen.org/gerrit/c/platform/core/uifw/voice-control/+/230142

Change-Id: I13d3c62eb06bdc0368b6c0b1bb3a6627dd4c70ef
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
client/CMakeLists.txt
client/vc_mgr.c
client/vc_mgr_ducking.c [new file with mode: 0644]
client/vc_mgr_ducking.h [new file with mode: 0644]

index 17a0edd..7b3a3d2 100644 (file)
@@ -1,4 +1,4 @@
-SET(SRCS 
+SET(SRCS
        vc.c
        vc_data.cpp
        vc_client.c
@@ -44,6 +44,7 @@ SET(MANAGER_SRCS
        vc_mgr_tidl.c
        vc_mgr_proxy.c
        vc_mgr_stub.c
+       vc_mgr_ducking.c
        ../common/vc_cmd_db.c
        ../common/vc_command.c
        ../common/vc_command_util.c
index 295fcf4..f3e65bb 100644 (file)
@@ -20,8 +20,6 @@
 #include <cynara-error.h>
 #include <cynara-session.h>
 #include <pthread.h>
-#include <sound_manager.h>
-#include <sound_manager_internal.h>
 #include <math.h>
 
 #include "vc_cmd_db.h"
@@ -34,6 +32,7 @@
 #include "vc_mgr_tidl.h"
 #include "vc_mgr_data.h"
 #include "vc_mgr_player.h"
+#include "vc_mgr_ducking.h"
 #include "voice_control_command.h"
 #include "voice_control_command_expand.h"
 #include "voice_control_common.h"
@@ -70,10 +69,6 @@ static pthread_mutex_t g_cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static bool g_err_callback_status = false;
 
-/* for changing volume on each sound stream */
-static sound_stream_info_h     g_stream_for_volume_h = NULL;
-static virtual_sound_stream_h  g_virtual_sound_stream_h = NULL;
-
 /* for TTS feedback */
 static int g_feedback_rate = 16000;
 static vc_audio_channel_e g_feedback_audio_channel = 0;
@@ -322,6 +317,12 @@ int vc_mgr_initialize(void)
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to initialize VC mgr player : %d", ret);
        }
 */
+
+       ret = vc_mgr_ducking_create();
+       if (VC_ERROR_NONE != ret) {
+               SLOG(LOG_INFO, TAG_VCM, "[INFO] Fail to ducking create : %d", ret);
+       }
+
        SLOG(LOG_ERROR, TAG_VCM, "[Success] pid(%d)", g_vc_m->handle);
 
        SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] Initialize DONE");
@@ -406,6 +407,11 @@ int vc_mgr_deinitialize(void)
        }
 */
 
+       ret = vc_mgr_ducking_destory();
+       if (VC_ERROR_NONE != ret) {
+               SLOG(LOG_INFO, TAG_VCM, "[INFO] Fail to ducking destory : %d", ret);
+       }
+
        if (0 != vc_mgr_tidl_close_connection()) {
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to close connection");
        }
@@ -3767,116 +3773,59 @@ int vc_mgr_set_audio_streaming_mode(vc_audio_streaming_mode_e mode)
        return VC_ERROR_NONE;
 }
 
-int __vc_change_system_volume(vc_system_volume_event_e volume_event)
+//TODO it's internal api, so will remove it.
+int vc_mgr_change_system_volume(vc_system_volume_event_e event)
 {
-       int stream_type = -1;
-       if (VC_SYSTEM_VOLUME_EVENT_CHANGE_FOR_FARFIELD == volume_event) {
-               stream_type = SOUND_STREAM_TYPE_VOICE_RECOGNITION;
-       } else if (VC_SYSTEM_VOLUME_EVENT_CHANGE_FOR_NEARFIELD == volume_event) {
-               stream_type = SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE;
-       } else {
-               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] volume type is invalid, type(%d)", volume_event);
-               return VC_ERROR_INVALID_PARAMETER;
-       }
-
-       SLOG(LOG_INFO, TAG_VCM, "[INFO] Change system volume, volume_type(%d)", volume_event);
+       return vc_mgr_change_background_volume(event);
+}
 
-       int ret = VC_ERROR_NONE;
-       /* destroy virtual - destroy stream info - create stream info - create virtual */
-       if (g_virtual_sound_stream_h) {
-               SLOG(LOG_INFO, TAG_VCM, "[INFO] Virtual stream is already created, destroy virtual stream)");
-               ret = sound_manager_stop_virtual_stream(g_virtual_sound_stream_h);
-               if (0 != ret) {
-                       SLOG(LOG_WARN, TAG_VCM, "[WARNING] Fail to stop virtual stream, ret(%d)", ret);
-               }
-               ret = sound_manager_destroy_virtual_stream(g_virtual_sound_stream_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy virtual stream, ret(%d)", ret);
-               }
-               g_virtual_sound_stream_h = NULL;
-       }
+//TODO it's internal api, so will remove it.
+int vc_mgr_recover_system_volume(void)
+{
+       return vc_mgr_reset_background_volume();
+}
 
-       if (g_stream_for_volume_h) {
-               SLOG(LOG_INFO, TAG_VCM, "[INFO] Stream is already created, destroy stream)");
-               ret = sound_manager_destroy_stream_information(g_stream_for_volume_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy stream information, ret(%d)", ret);
-               }
-               g_stream_for_volume_h = NULL;
-       }
+int vc_mgr_change_background_volume(vc_background_volume_event_e event)
+{
+       SLOG(LOG_INFO, TAG_VCM, "[Manager] Change system volume");
 
-       ret = sound_manager_create_stream_information_internal(stream_type, NULL, NULL, &g_stream_for_volume_h);
-       if (0 != ret) {
-               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to create stream information, ret(%d)", ret);
-               return VC_ERROR_OPERATION_FAILED;
-       }
+       int ret;
+       ret = __check_mgr_feature_privilege();
+       if (VC_ERROR_NONE != ret)
+               return ret;
 
-       ret = sound_manager_create_virtual_stream(g_stream_for_volume_h, &g_virtual_sound_stream_h);
-       if (0 != ret) {
-               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to create virtual stream, ret(%d)", ret);
-               ret = sound_manager_destroy_stream_information(g_stream_for_volume_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy stream information, ret(%d)", ret);
-               }
-               g_stream_for_volume_h = NULL;
-               return VC_ERROR_OPERATION_FAILED;
+       if (VC_BACKGROUND_VOLUME_EVENT_CHANGE_FOR_NEARFIELD > event || VC_BACKGROUND_VOLUME_EVENT_CHANGE_FOR_FARFIELD < event) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] event is invalid parameter (%d)", event);
+               return VC_ERROR_INVALID_PARAMETER;
        }
 
-       ret = sound_manager_start_virtual_stream(g_virtual_sound_stream_h);
+       vc_state_e state = VC_STATE_NONE;
+       ret = vc_mgr_client_get_client_state(g_vc_m, &state);
        if (0 != ret) {
-               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to start virtual stream, ret(%d)", ret);
-               ret = sound_manager_destroy_virtual_stream(g_virtual_sound_stream_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy virtual stream, ret(%d)", ret);
-               }
-               g_virtual_sound_stream_h = NULL;
-
-               ret = sound_manager_destroy_stream_information(g_stream_for_volume_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy stream information, ret(%d)", ret);
-               }
-               g_stream_for_volume_h = NULL;
-
-               return VC_ERROR_OPERATION_FAILED;
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available");
+               return VC_ERROR_INVALID_STATE;
        }
 
-       SLOG(LOG_INFO, TAG_VCM, "[SUCCESS] Change system volume");
-       return VC_ERROR_NONE;
-}
-
-int __vc_recover_system_volume()
-{
-       SLOG(LOG_INFO, TAG_VCM, "[INFO] Recover system volume");
-
-       int ret = VC_ERROR_NONE;
-
-       if (g_virtual_sound_stream_h) {
-               ret = sound_manager_stop_virtual_stream(g_virtual_sound_stream_h);
-               if (0 != ret) {
-                       SLOG(LOG_WARN, TAG_VCM, "[WARNING] Fail to stop virtual stream, ret(%d)", ret);
-               }
-               ret = sound_manager_destroy_virtual_stream(g_virtual_sound_stream_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy virtual stream, ret(%d)", ret);
-                       return VC_ERROR_OPERATION_FAILED;
-               }
-               g_virtual_sound_stream_h = NULL;
+       if (state != VC_STATE_READY && state != VC_STATE_INITIALIZED) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY' and not 'INITIALIZED', state(%d)", state);
+               return VC_ERROR_INVALID_STATE;
        }
 
-       if (g_stream_for_volume_h) {
-               ret = sound_manager_destroy_stream_information(g_stream_for_volume_h);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to destroy stream information, ret(%d)", ret);
-                       return VC_ERROR_OPERATION_FAILED;
-               }
-               g_stream_for_volume_h = NULL;
-       }
+       double ratio = 0.0;
+       if (VC_BACKGROUND_VOLUME_EVENT_CHANGE_FOR_FARFIELD == event)
+               ratio = 0.0;
+       else if (VC_BACKGROUND_VOLUME_EVENT_CHANGE_FOR_NEARFIELD == event)
+               ratio = 0.7;
 
-       SLOG(LOG_INFO, TAG_VCM, "[SUCCESS] Recover system volume");
-       return VC_ERROR_NONE;
+       ret = vc_mgr_ducking_activate(ratio);
+       if (0 != ret)
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to change volume");
+       else
+               SLOG(LOG_INFO, TAG_VCM, "[DEBUG] Success to change volume");
+       return ret;
 }
 
-int vc_mgr_change_system_volume(vc_system_volume_event_e event)
+int vc_mgr_change_background_volume_by_ratio(double ratio)
 {
        SLOG(LOG_INFO, TAG_VCM, "[Manager] Change system volume");
 
@@ -3885,12 +3834,12 @@ int vc_mgr_change_system_volume(vc_system_volume_event_e event)
        if (VC_ERROR_NONE != ret)
                return ret;
 
-       if (VC_SYSTEM_VOLUME_EVENT_CHANGE_FOR_NEARFIELD > event || VC_SYSTEM_VOLUME_EVENT_CHANGE_FOR_FARFIELD < event) {
-               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] event is invalid parameter (%d)", event);
+       if (0.0 > ratio || 1.0 < ratio) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] ratio is invalid parameter (%lf)", ratio);
                return VC_ERROR_INVALID_PARAMETER;
        }
 
-       vc_state_e state;
+       vc_state_e state = VC_STATE_NONE;
        ret = vc_mgr_client_get_client_state(g_vc_m, &state);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available");
@@ -3902,15 +3851,15 @@ int vc_mgr_change_system_volume(vc_system_volume_event_e event)
                return VC_ERROR_INVALID_STATE;
        }
 
-       ret = __vc_change_system_volume(event);
+       ret = vc_mgr_ducking_activate(ratio);
        if (0 != ret)
-               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to change volume");
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set ratio");
        else
-               SLOG(LOG_INFO, TAG_VCM, "[DEBUG] Success to change volume");
+               SLOG(LOG_INFO, TAG_VCM, "[DEBUG] Success to set ratio");
        return ret;
 }
 
-int vc_mgr_recover_system_volume(void)
+int vc_mgr_reset_background_volume(void)
 {
        SLOG(LOG_INFO, TAG_VCM, "[Manager] recover system volume");
 
@@ -3931,8 +3880,7 @@ int vc_mgr_recover_system_volume(void)
                return VC_ERROR_INVALID_STATE;
        }
 
-       /* recover volume */
-       ret = __vc_recover_system_volume();
+       ret = vc_mgr_ducking_deactivate();
        if (0 != ret)
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to recover volume");
        else
diff --git a/client/vc_mgr_ducking.c b/client/vc_mgr_ducking.c
new file mode 100644 (file)
index 0000000..a8555ad
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "vc_main.h"
+#include "voice_control_common.h"
+#include "vc_mgr_ducking.h"
+#include <sound_manager.h>
+
+#define SND_MGR_DUCKING_DURATION 500
+
+/* for changing volume on each sound stream */
+static sound_stream_ducking_h g_media_stream_h = NULL;
+static sound_stream_ducking_h g_system_stream_h = NULL;
+static sound_stream_ducking_h g_notification_stream_h = NULL;
+static sound_stream_ducking_h g_alarm_stream_h = NULL;
+
+static char *__get_ducking_stream(sound_stream_type_e stream_type);
+static int __activate_ducking_sound_stream(sound_stream_type_e type, sound_stream_ducking_h header, double ratio);
+static int __deactivate_ducking_sound_stream(sound_stream_type_e type, sound_stream_ducking_h header);
+
+int vc_mgr_ducking_create(void)
+{
+    int ret = VC_ERROR_NONE;
+
+    if (g_media_stream_h) {
+        SLOG(LOG_INFO, TAG_VCM, "Ducking handle for media stream is already created");
+    } else {
+        ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &g_media_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret) {
+            g_media_stream_h = NULL;
+            SLOG(LOG_ERROR, TAG_VCM, "Fail to create stream ducking for type media, ret(%d)", ret);
+            return ret;
+        }
+    }
+
+    if (g_system_stream_h) {
+        SLOG(LOG_INFO, TAG_VCM, "Ducking handle for system stream is already created");
+    } else {
+        ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_SYSTEM, NULL, NULL, &g_system_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret) {
+                   sound_manager_destroy_stream_ducking(g_media_stream_h);
+            g_media_stream_h = NULL;
+            g_system_stream_h = NULL;
+            SLOG(LOG_ERROR, TAG_VCM, "Fail to create stream ducking for type system, ret(%d)", ret);
+            return ret;
+        }
+    }
+
+    if (g_notification_stream_h) {
+        SLOG(LOG_INFO, TAG_VCM, "Ducking handle for notification stream is already created");
+    } else {
+        ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_NOTIFICATION, NULL, NULL, &g_notification_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret) {
+                   sound_manager_destroy_stream_ducking(g_media_stream_h);
+                   sound_manager_destroy_stream_ducking(g_system_stream_h);
+            g_media_stream_h = NULL;
+            g_system_stream_h = NULL;
+            g_notification_stream_h = NULL;
+            SLOG(LOG_ERROR, TAG_VCM, "Fail to create stream ducking for type notification, ret(%d)", ret);
+            return ret;
+        }
+    }
+
+    if (g_alarm_stream_h) {
+        SLOG(LOG_INFO, TAG_VCM, "Ducking handle for alarm stream is already created");
+    } else {
+        ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_ALARM, NULL, NULL, &g_alarm_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret) {
+                   sound_manager_destroy_stream_ducking(g_media_stream_h);
+                   sound_manager_destroy_stream_ducking(g_system_stream_h);
+                   sound_manager_destroy_stream_ducking(g_system_stream_h);
+            g_media_stream_h = NULL;
+            g_system_stream_h = NULL;
+            g_notification_stream_h = NULL;
+            g_alarm_stream_h = NULL;
+            SLOG(LOG_ERROR, TAG_VCM, "Fail to create stream ducking for type media, ret(%d)", ret);
+            return ret;
+        }
+    }
+
+    return VC_ERROR_NONE;
+}
+
+int vc_mgr_ducking_destory(void)
+{
+    int ret = VC_ERROR_NONE;
+
+    if (g_media_stream_h) {
+        ret = sound_manager_destroy_stream_ducking(g_media_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret)
+            SLOG(LOG_WARN, TAG_VCM, "Fail to destroy media stream ducking, ret(%d)", ret);
+        g_media_stream_h = NULL;
+    } else {
+        SLOG(LOG_INFO, TAG_VCM, "[Volume INFO] Ducking handle for media stream is already created");
+    }
+
+    if (g_system_stream_h) {
+               ret = sound_manager_destroy_stream_ducking(g_system_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret)
+            SLOG(LOG_WARN, TAG_VCM, "[Volume WARNING] Fail to destroy system stream ducking, ret(%d)", ret);
+        g_system_stream_h = NULL;
+    } else {
+               SLOG(LOG_INFO, TAG_VCM, "[Volume INFO] Ducking handle for system stream is already created");
+       }
+
+       if (g_notification_stream_h) {
+               ret = sound_manager_destroy_stream_ducking(g_notification_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret)
+            SLOG(LOG_WARN, TAG_VCM, "[Volume WARNING] Fail to destroy notification stream ducking, ret(%d)", ret);
+        g_notification_stream_h = NULL;
+    } else {
+               SLOG(LOG_INFO, TAG_VCM, "[Volume INFO] Ducking handle for notification stream is already created");
+       }
+
+       if (g_alarm_stream_h) {
+               ret = sound_manager_destroy_stream_ducking(g_alarm_stream_h);
+        if (SOUND_MANAGER_ERROR_NONE != ret)
+            SLOG(LOG_WARN, TAG_VCM, "[Volume WARNING] Fail to destroy alarm stream ducking, ret(%d)", ret);
+        g_alarm_stream_h = NULL;
+    } else {
+               SLOG(LOG_INFO, TAG_VCM, "[Volume INFO] Ducking handle for alarm stream is already created");
+       }
+
+    return VC_ERROR_NONE;
+}
+
+int vc_mgr_ducking_activate(double ratio)
+{
+    SLOG(LOG_INFO, TAG_VCM, "vc_mgr_ducking_activate ratio(%lf)", ratio);
+
+    int ret = VC_ERROR_NONE;
+    ret = __activate_ducking_sound_stream(SOUND_STREAM_TYPE_MEDIA, g_media_stream_h, ratio);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        return ret;
+    ret = __activate_ducking_sound_stream(SOUND_STREAM_TYPE_SYSTEM, g_system_stream_h, ratio);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        return ret;
+    ret = __activate_ducking_sound_stream(SOUND_STREAM_TYPE_NOTIFICATION, g_notification_stream_h, ratio);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        return ret;
+    ret = __activate_ducking_sound_stream(SOUND_STREAM_TYPE_ALARM, g_alarm_stream_h, ratio);
+    return ret;
+}
+
+int vc_mgr_ducking_deactivate(void)
+{
+    SLOG(LOG_INFO, TAG_VCM, "vc_mgr_ducking_deactivate");
+
+    int ret = VC_ERROR_NONE;
+    ret = __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_MEDIA, g_media_stream_h);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        return ret;
+    ret = __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_SYSTEM, g_system_stream_h);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        return ret;
+    ret = __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_NOTIFICATION, g_notification_stream_h);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        return ret;
+    ret = __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_ALARM, g_alarm_stream_h);
+    return ret;
+}
+
+static char *__get_ducking_stream(sound_stream_type_e stream_type)
+{
+    if (SOUND_STREAM_TYPE_MEDIA == stream_type)
+        return "Media stream";
+    else if (SOUND_STREAM_TYPE_SYSTEM == stream_type)
+        return "System stream";
+    else if (SOUND_STREAM_TYPE_NOTIFICATION == stream_type)
+        return "Notification stream";
+    else if (SOUND_STREAM_TYPE_ALARM == stream_type)
+        return "Alarm stream";
+    return "Non matched stream";
+}
+
+static int __activate_ducking_sound_stream(sound_stream_type_e type, sound_stream_ducking_h header, double ratio)
+{
+    bool is_ducked = false;
+    int ret = SOUND_MANAGER_ERROR_NONE;
+    ret = sound_manager_is_ducked(header, &is_ducked);
+    if (is_ducked) {
+        SLOG(LOG_DEBUG, TAG_VCM, "The %s is already ducked", __get_ducking_stream(type));
+        return ret;
+    }
+
+    ret = sound_manager_activate_ducking(header, SND_MGR_DUCKING_DURATION, ratio);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        SLOG(LOG_ERROR, TAG_VCM, "Fail to activate ducking for %s", __get_ducking_stream(type));
+    else
+        SLOG(LOG_INFO, TAG_VCM, "Activate ducking for %s", __get_ducking_stream(type));
+    return ret;
+}
+
+static int __deactivate_ducking_sound_stream(sound_stream_type_e type, sound_stream_ducking_h header)
+{
+    bool is_ducked = false;
+    int ret = SOUND_MANAGER_ERROR_NONE;
+    ret = sound_manager_is_ducked(header, &is_ducked);
+    if (false == is_ducked) {
+        SLOG(LOG_DEBUG, TAG_VCM, "The %s is already recovered from ducking", __get_ducking_stream(type));
+        return ret;
+    }
+
+    ret = sound_manager_deactivate_ducking(header);
+    if (SOUND_MANAGER_ERROR_NONE != ret)
+        SLOG(LOG_ERROR, TAG_VCM, "Fail to deactivate ducking for %s", __get_ducking_stream(type));
+    else
+        SLOG(LOG_INFO, TAG_VCM, "Deactivate ducking for %s", __get_ducking_stream(type));
+    return ret;
+}
diff --git a/client/vc_mgr_ducking.h b/client/vc_mgr_ducking.h
new file mode 100644 (file)
index 0000000..56ada10
--- /dev/null
@@ -0,0 +1,19 @@
+
+#ifndef __VC_MGR_DUCKING_H__
+#define __VC_MGR_DUCKING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int vc_mgr_ducking_create(void);
+int vc_mgr_ducking_destory(void);
+
+int vc_mgr_ducking_activate(double ratio);
+int vc_mgr_ducking_deactivate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VC_MGR_DUCKING_H__ */