Merge "Fix potential defects on ttsd_player" into tizen
authorSuyeon Hwang <stom.hwang@samsung.com>
Thu, 17 Feb 2022 02:46:48 +0000 (02:46 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 17 Feb 2022 02:46:48 +0000 (02:46 +0000)
server/BackgroundVolume.cpp [new file with mode: 0644]
server/BackgroundVolume.h [new file with mode: 0644]
server/CMakeLists.txt
server/ttsd_player.cpp
server/ttsd_server.c

diff --git a/server/BackgroundVolume.cpp b/server/BackgroundVolume.cpp
new file mode 100644 (file)
index 0000000..8c5e9af
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+*  Copyright (c) 2021 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 "ttsd_main.h"
+
+#include "BackgroundVolume.h"
+
+
+using namespace std;
+
+static const char* __get_ducking_stream(sound_stream_type_e stream_type)
+{
+       switch (stream_type)
+       {
+       case SOUND_STREAM_TYPE_MEDIA:
+               return "Media stream";
+       case SOUND_STREAM_TYPE_NOTIFICATION:
+               return "Notification stream";
+       case SOUND_STREAM_TYPE_ALARM:
+               return "Alarm stream";
+
+       default:
+               SLOG(LOG_DEBUG, tts_tag(), "[BackgroundVolume] Type is not handled. type(%d)", stream_type);
+               break;
+       }
+
+       return "Non matched stream";
+}
+
+static void __sound_stream_ducking_state_changed_cb(sound_stream_ducking_h stream_ducking, bool is_ducked, void *user_data)
+{
+       SLOG(LOG_DEBUG, tts_tag(), "[BackgroundVolume] is ducked : %d", is_ducked);
+       return;
+}
+
+BackgroundVolume::BackgroundVolume(long long int duckingDuration):
+               __duckingDuration(duckingDuration), __postponedRecoverTimer(nullptr), __postponedModifyTimer(nullptr)
+{
+       int ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_MEDIA, __sound_stream_ducking_state_changed_cb, nullptr, &__mediaStream);
+       if (SOUND_MANAGER_ERROR_NONE != ret)
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for type media, ret(%d)", ret);
+
+       ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_NOTIFICATION, __sound_stream_ducking_state_changed_cb, nullptr, &__notificationStream);
+       if (SOUND_MANAGER_ERROR_NONE != ret)
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for notification type, ret(%d)", ret);
+
+       ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_ALARM, __sound_stream_ducking_state_changed_cb, nullptr, &__alarmStream);
+       if (SOUND_MANAGER_ERROR_NONE != ret)
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to create stream ducking for alarm type, ret(%d)", ret);
+
+       __isVolumeDucked = false;
+       __volumeRatio = 0.0;
+}
+
+BackgroundVolume::~BackgroundVolume()
+{
+       long long int diff = getDurationAfterDucking();
+       if (diff < __duckingDuration) {
+               usleep(__duckingDuration * 1000);
+       }
+
+       deactivateDuckingAll();
+
+       if (nullptr != __postponedModifyTimer) {
+               void* result = ecore_timer_del(__postponedModifyTimer);
+               __postponedModifyTimer = nullptr;
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Remove modification timer. result(%p)", result);
+       }
+
+       if (nullptr != __postponedRecoverTimer) {
+               void* result = ecore_timer_del(__postponedRecoverTimer);
+               __postponedRecoverTimer = nullptr;
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Remove recover timer. result(%p)", result);
+       }
+
+       if (__mediaStream) {
+               int ret = sound_manager_destroy_stream_ducking(__mediaStream);
+               if (SOUND_MANAGER_ERROR_NONE != ret)
+                       SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to destroy media stream ducking, ret(%d)", ret);
+               __mediaStream = nullptr;
+       } else {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Ducking handle for media stream is already destroyed");
+       }
+
+       if (__notificationStream) {
+               int ret = sound_manager_destroy_stream_ducking(__notificationStream);
+               if (SOUND_MANAGER_ERROR_NONE != ret)
+                       SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to destroy notification stream ducking, ret(%d)", ret);
+               __notificationStream = nullptr;
+       } else {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Ducking handle for notification stream is already destroyed");
+       }
+
+       if (__alarmStream) {
+               int ret = sound_manager_destroy_stream_ducking(__alarmStream);
+               if (SOUND_MANAGER_ERROR_NONE != ret)
+                       SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to destroy alarm stream ducking, ret(%d)", ret);
+               __alarmStream = nullptr;
+       } else {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Ducking handle for alarm stream is already destroyed");
+       }
+}
+
+void BackgroundVolume::setVolumeRatio(double ratio)
+{
+       if (__volumeRatio.load() == ratio) {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Volume is not changed (%lf).", ratio);
+               return;
+       }
+
+       __volumeRatio = ratio;
+       ecore_main_loop_thread_safe_call_async(modifyVolumeOnMainThread, static_cast<void*>(this));
+}
+
+void BackgroundVolume::modifyVolumeOnMainThread(void* data)
+{
+       if (nullptr == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid data is passed");
+               return;
+       }
+
+       BackgroundVolume* backgroundVolume = static_cast<BackgroundVolume*>(data);
+       if (!backgroundVolume->__isVolumeDucked.load()) {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Volume is not changed yet.");
+               return;
+       }
+
+       if (backgroundVolume->__postponedModifyTimer != nullptr) {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Reserved volume modification exist. (%p)", backgroundVolume->__postponedModifyTimer);
+               return;
+       }
+
+       long long int diff = backgroundVolume->getDurationAfterDucking();
+       if (diff >= backgroundVolume->__duckingDuration) {
+               double ratio = backgroundVolume->__volumeRatio.load();
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Modify volume ratio(%lf) directly", ratio);
+
+               backgroundVolume->deactivateDuckingAll();
+               backgroundVolume->activateDuckingAll(0, ratio);
+       } else {
+               double delay = static_cast<double>(backgroundVolume->__duckingDuration - diff) / 1000.0;
+               backgroundVolume->__postponedModifyTimer = ecore_timer_add(delay, postponedModifyTimerCb, data);
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Delay volume modification (%p), delay(%lf)", backgroundVolume->__postponedModifyTimer, delay);
+       }
+}
+
+Eina_Bool BackgroundVolume::postponedModifyTimerCb(void* data)
+{
+       if (nullptr == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid data is passed");
+               return EINA_FALSE;
+       }
+
+       BackgroundVolume* backgroundVolume = static_cast<BackgroundVolume*>(data);
+       double ratio = backgroundVolume->__volumeRatio.load();
+       backgroundVolume->deactivateDuckingAll();
+       backgroundVolume->activateDuckingAll(0, ratio);
+
+       SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Delayed volume modification success. ratio(%lf)", ratio);
+       backgroundVolume->__postponedModifyTimer = nullptr;
+       return EINA_FALSE;
+}
+
+double BackgroundVolume::getVolumeRatio()
+{
+       return __volumeRatio.load();
+}
+
+void BackgroundVolume::applyVolumeRatio()
+{
+       __isVolumeDucked = true;
+       ecore_main_loop_thread_safe_call_async(changeVolumeOnMainThread, static_cast<void*>(this));
+}
+
+void BackgroundVolume::changeVolumeOnMainThread(void* data)
+{
+       if (nullptr == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid data is passed");
+               return;
+       }
+
+       BackgroundVolume* backgroundVolume = static_cast<BackgroundVolume*>(data);
+       if (nullptr != backgroundVolume->__postponedRecoverTimer) {
+               void* result = ecore_timer_del(backgroundVolume->__postponedRecoverTimer);
+               backgroundVolume->__postponedRecoverTimer = nullptr;
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Remove recover timer. result(%p)", result);
+       }
+
+       double ratio = backgroundVolume->__volumeRatio.load();
+       SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Volume ratio(%lf)", ratio);
+       if (0.0 > ratio || 1.0 < ratio) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid ratio(%lf)", ratio);
+               return;
+       }
+
+       backgroundVolume->activateDuckingAll(backgroundVolume->__duckingDuration, ratio);
+}
+
+void BackgroundVolume::activateDuckingAll(unsigned int duration, double ratio)
+{
+       activateDucking(SOUND_STREAM_TYPE_MEDIA, duration, ratio);
+       activateDucking(SOUND_STREAM_TYPE_NOTIFICATION, duration, ratio);
+       activateDucking(SOUND_STREAM_TYPE_ALARM, duration, ratio);
+
+       __changeVolumeTime = chrono::steady_clock::now();
+}
+
+bool BackgroundVolume::activateDucking(sound_stream_type_e type, unsigned int duration, double ratio)
+{
+       bool isDucked = false;
+       sound_stream_ducking_h handle = getStreamDuckingHandle(type);
+       sound_manager_is_ducked(handle, &isDucked);
+       if (isDucked) {
+               SLOG(LOG_DEBUG, tts_tag(), "[BackgroundVolume] The %s is already ducked", __get_ducking_stream(type));
+               return false;
+       }
+
+       if (SOUND_MANAGER_ERROR_NONE != sound_manager_activate_ducking(handle, duration, ratio)) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Fail to activate ducking for %s", __get_ducking_stream(type));
+               return false;
+       }
+
+       SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Activate ducking for %s", __get_ducking_stream(type));
+       return true;
+}
+
+void BackgroundVolume::recoverVolumeRatio()
+{
+       __isVolumeDucked = false;
+       ecore_main_loop_thread_safe_call_async(recoverVolumeOnMainThread, static_cast<void*>(this));
+}
+
+void BackgroundVolume::recoverVolumeOnMainThread(void* data)
+{
+       if (nullptr == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid data is passed");
+               return;
+       }
+
+       BackgroundVolume* backgroundVolume = static_cast<BackgroundVolume*>(data);
+       if (nullptr != backgroundVolume->__postponedRecoverTimer) {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Reserved volume recover exist. (%p)", backgroundVolume->__postponedRecoverTimer);
+               return;
+       }
+
+       if (nullptr != backgroundVolume->__postponedModifyTimer) {
+               void* result = ecore_timer_del(backgroundVolume->__postponedModifyTimer);
+               backgroundVolume->__postponedModifyTimer = nullptr;
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Remove modification timer. result(%p)", result);
+       }
+
+       long long int diff = backgroundVolume->getDurationAfterDucking();
+       if (diff >= backgroundVolume->__duckingDuration) {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Direct deactivate ducking");
+
+               backgroundVolume->deactivateDuckingAll();
+       } else {
+               double delay = static_cast<double>(backgroundVolume->__duckingDuration - diff) / 1000.0;
+               backgroundVolume->__postponedRecoverTimer = ecore_timer_add(delay, postponedRecoverTimerCb, data);
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Delay deactivate ducking (%p), delay(%f)", backgroundVolume->__postponedRecoverTimer, delay);
+       }
+}
+
+long long int BackgroundVolume::getDurationAfterDucking()
+{
+       auto currentTime = chrono::steady_clock::now();
+       chrono::milliseconds diff = chrono::duration_cast<chrono::milliseconds>(currentTime - __changeVolumeTime);
+
+       return diff.count();
+}
+
+void BackgroundVolume::deactivateDuckingAll()
+{
+       deactivateDucking(SOUND_STREAM_TYPE_MEDIA);
+       deactivateDucking(SOUND_STREAM_TYPE_NOTIFICATION);
+       deactivateDucking(SOUND_STREAM_TYPE_ALARM);
+}
+
+Eina_Bool BackgroundVolume::postponedRecoverTimerCb(void* data)
+{
+       if (nullptr == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid data is passed");
+               return EINA_FALSE;
+       }
+
+       BackgroundVolume* backgroundVolume = static_cast<BackgroundVolume*>(data);
+       backgroundVolume->deactivateDuckingAll();
+       backgroundVolume->__postponedRecoverTimer = nullptr;
+
+       SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Delayed unset policy success");
+       return EINA_FALSE;
+}
+
+void BackgroundVolume::deactivateDucking(sound_stream_type_e type)
+{
+       bool isDucked = false;
+       sound_stream_ducking_h handle = getStreamDuckingHandle(type);
+       sound_manager_is_ducked(handle, &isDucked);
+       if (!isDucked) {
+               SLOG(LOG_DEBUG, tts_tag(), "[BackgroundVolume] The %s is already recovered from ducking", __get_ducking_stream(type));
+               return;
+       }
+
+       if (SOUND_MANAGER_ERROR_NONE != sound_manager_deactivate_ducking(handle)) {
+               SLOG(LOG_WARN, tts_tag(), "[BackgroundVolume] Fail to deactivate ducking for %s", __get_ducking_stream(type));
+       } else {
+               SLOG(LOG_INFO, tts_tag(), "[BackgroundVolume] Deactivate ducking for %s", __get_ducking_stream(type));
+       }
+}
+
+sound_stream_ducking_h BackgroundVolume::getStreamDuckingHandle(sound_stream_type_e type)
+{
+       switch (type)
+       {
+       case SOUND_STREAM_TYPE_MEDIA:
+               return __mediaStream;
+       case SOUND_STREAM_TYPE_NOTIFICATION:
+               return __notificationStream;
+       case SOUND_STREAM_TYPE_ALARM:
+               return __alarmStream;
+
+       default:
+               SLOG(LOG_ERROR, tts_tag(), "[BackgroundVolume] Invalid stream type (%d)", type);
+               break;
+       }
+
+       return nullptr;
+}
diff --git a/server/BackgroundVolume.h b/server/BackgroundVolume.h
new file mode 100644 (file)
index 0000000..bc61b1f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+*  Copyright (c) 2021 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.
+*/
+
+#ifndef __TTSD_BACKGROUND_VOLUME_H_
+#define __TTSD_BACKGROUND_VOLUME_H_
+
+
+#include <mutex>
+#include <chrono>
+#include <atomic>
+#include <Ecore.h>
+
+#include <sound_manager.h>
+
+#include "ttse.h"
+
+class BackgroundVolume {
+public:
+       BackgroundVolume(long long int duckingDuration);
+       ~BackgroundVolume();
+
+       void setVolumeRatio(double ratio);
+       double getVolumeRatio();
+       void applyVolumeRatio();
+       void recoverVolumeRatio();
+
+private:
+       static void changeVolumeOnMainThread(void* data);
+       static void modifyVolumeOnMainThread(void* data);
+       static void recoverVolumeOnMainThread(void* data);
+       static Eina_Bool postponedRecoverTimerCb(void* data);
+       static Eina_Bool postponedModifyTimerCb(void* data);
+
+       long long int getDurationAfterDucking();
+       sound_stream_ducking_h getStreamDuckingHandle(sound_stream_type_e type);
+
+       void activateDuckingAll(unsigned int duration, double ratio);
+       bool activateDucking(sound_stream_type_e type, unsigned int duration, double ratio);
+       void deactivateDuckingAll();
+       void deactivateDucking(sound_stream_type_e type);
+
+private:
+       const long long int __duckingDuration;
+       sound_stream_ducking_h __mediaStream;
+       sound_stream_ducking_h __notificationStream;
+       sound_stream_ducking_h __alarmStream;
+       std::atomic<double> __volumeRatio;
+       std::atomic<bool> __isVolumeDucked;
+
+       std::chrono::time_point<std::chrono::steady_clock> __changeVolumeTime;
+       Ecore_Timer* __postponedRecoverTimer;
+       Ecore_Timer* __postponedModifyTimer;
+};
+
+
+#endif /* __TTSD_BACKGROUND_VOLUME_H_ */
index 3d0b98f..25f710a 100644 (file)
@@ -10,6 +10,7 @@ SET(SRCS
        ttse.c
        ttsd_network.c
        ttsd_player.cpp
+       BackgroundVolume.cpp
        ttsd_server.c
        ../common/tts_config_mgr.c
        ../common/tts_config_parser.c
index 80b3a80..3547454 100644 (file)
@@ -14,9 +14,7 @@
 #include <audio_io.h>
 #include <Ecore.h>
 #include <sound_manager.h>
-#include <sound_manager_internal.h>
 #include <pthread.h>
-#include <time.h>
 
 #include "ttsd_main.h"
 #include "ttsd_player.h"
@@ -24,6 +22,8 @@
 #include "ttsd_dbus.h"
 #include "ttsd_ipc.h"
 
+#include "BackgroundVolume.h"
+
 #include "tts_internal.h"
 #include "ttsd_server.h"
 
@@ -88,31 +88,21 @@ static audio_out_h g_audio_h;
 
 static sound_stream_info_h g_stream_info_h;
 
-static sound_stream_ducking_h g_media_stream_ducking;
-//static sound_stream_ducking_h g_system_stream_ducking;
-static sound_stream_ducking_h g_notification_stream_ducking;
-static sound_stream_ducking_h g_alarm_stream_ducking;
-
 static bool g_is_set_policy;
 
-// static bool ducking_flag;
-
 /* CAUTION!
 If you change this constant value. Please check the function '__set_timer_for_delay_recover()'.
 If you choose too big value, it may cause integer overflow issue.
 */
 #define SND_MGR_DUCKING_DURATION 500
 
-static struct timespec g_policy_set_time;
-static Ecore_Timer* g_delayed_unset_policy_timer = NULL;
-static Ecore_Timer* g_modify_background_volume = NULL;
-
-static double g_bg_volume_ratio;
-
 static pthread_mutex_t g_play_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t g_player_control_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static pthread_cond_t g_play_thread_cond = PTHREAD_COND_INITIALIZER;
+
+static BackgroundVolume* g_background_volume = nullptr;
+
 /*
 * Internal Interfaces
 */
@@ -313,90 +303,6 @@ static void __player_focus_state_cb(sound_stream_info_h stream_info, sound_strea
        return;
 }
 
-void __sound_stream_ducking_state_changed_cb(sound_stream_ducking_h stream_ducking, bool is_ducked, void *user_data)
-{
-       SLOG(LOG_DEBUG, tts_tag(), "@@@ ducking state changed cb");
-       SLOG(LOG_ERROR, tts_tag(), "[Player] ducking_h(%p) is ducked : %d", stream_ducking, is_ducked);
-       // ducking_flag = true;
-       return;
-}
-
-static const char* __get_ducking_stream(sound_stream_type_e stream_type)
-{
-       const char* type = nullptr;
-       if (SOUND_STREAM_TYPE_MEDIA == stream_type)
-               type = "Media stream";
-       else if (SOUND_STREAM_TYPE_SYSTEM == stream_type)
-               type = "System stream";
-       else if (SOUND_STREAM_TYPE_NOTIFICATION == stream_type)
-               type = "Notification stream";
-       else if (SOUND_STREAM_TYPE_ALARM == stream_type)
-               type = "Alarm stream";
-       else
-               type = "Non matched stream";
-
-       return type;
-}
-
-static int __activate_ducking_sound_stream(sound_stream_type_e stream_type, sound_stream_ducking_h stream_ducking_h, unsigned int duration)
-{
-       bool is_ducked = false;
-       int ret = sound_manager_is_ducked(stream_ducking_h, &is_ducked);
-       if (is_ducked) {
-               SLOG(LOG_DEBUG, tts_tag(), "[Player] The %s is already ducked", __get_ducking_stream(stream_type));
-       } else {
-               ret = sound_manager_activate_ducking(stream_ducking_h, duration, g_bg_volume_ratio);
-               if (SOUND_MANAGER_ERROR_NONE != ret) {
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to activate ducking for %s", __get_ducking_stream(stream_type));
-               } else {
-                       SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Activate ducking for %s", __get_ducking_stream(stream_type));
-               }
-       }
-       return ret;
-}
-
-static void __change_background_volume(unsigned int duration)
-{
-       SLOG(LOG_INFO, tts_tag(), "[BG] Change background volume");
-       SLOG(LOG_INFO, tts_tag(), "[Player] volume ratio(%lf)", g_bg_volume_ratio);
-       if (1.0 > g_bg_volume_ratio) {
-               __activate_ducking_sound_stream(SOUND_STREAM_TYPE_MEDIA, g_media_stream_ducking, duration);
-//             __activate_ducking_sound_stream(SOUND_STREAM_TYPE_SYSTEM, g_system_stream_ducking, duration);
-               __activate_ducking_sound_stream(SOUND_STREAM_TYPE_NOTIFICATION, g_notification_stream_ducking, duration);
-               __activate_ducking_sound_stream(SOUND_STREAM_TYPE_ALARM, g_alarm_stream_ducking, duration);
-       }
-}
-
-static void __change_background_volume_async(void* data)
-{
-       __change_background_volume(SND_MGR_DUCKING_DURATION);
-}
-
-static int __deactivate_ducking_sound_stream(sound_stream_type_e stream_type, sound_stream_ducking_h stream_ducking_h)
-{
-       bool is_ducked = false;
-       int ret = sound_manager_is_ducked(stream_ducking_h, &is_ducked);
-       if (!is_ducked) {
-               SLOG(LOG_DEBUG, tts_tag(), "[Player] The %s is already recovered from ducking", __get_ducking_stream(stream_type));
-       } else {
-               ret = sound_manager_deactivate_ducking(stream_ducking_h);
-               if (SOUND_MANAGER_ERROR_NONE != ret) {
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to deactivate ducking for %s", __get_ducking_stream(stream_type));
-               } else {
-                       SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Deactivate ducking for %s", __get_ducking_stream(stream_type));
-               }
-       }
-       return ret;
-}
-
-static void __recover_background_volume()
-{
-       __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_MEDIA, g_media_stream_ducking);
-//     __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_SYSTEM, g_system_stream_ducking);
-       __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_NOTIFICATION, g_notification_stream_ducking);
-       __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_ALARM, g_alarm_stream_ducking);
-}
-
 static int __create_audio_out(ttse_audio_type_e type, int rate)
 {
        int ret = -1;
@@ -456,19 +362,8 @@ static void __end_play_thread(void *data, Ecore_Thread *thread)
        SLOG(LOG_ERROR, tts_tag(), "@@@ End thread");
 }
 
-static void __del_timer_for_delayed_recover(void* data)
-{
-       if (NULL != g_delayed_unset_policy_timer) {
-               int result = (intptr_t)ecore_timer_del(g_delayed_unset_policy_timer);
-               g_delayed_unset_policy_timer = NULL;
-               SLOG(LOG_ERROR, tts_tag(), "[BG] Remove timer (%d)", result);
-       }
-}
-
 static void __set_policy_for_playing(void)
 {
-       ecore_main_loop_thread_safe_call_async(__del_timer_for_delayed_recover, NULL);
-
        /* Set stream info */
        const char* extra_info = NULL;
        if (TTSD_MODE_INTERRUPT == ttsd_get_mode()) {
@@ -487,56 +382,14 @@ static void __set_policy_for_playing(void)
                SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to set stream info");
        }
 
-       ecore_main_loop_thread_safe_call_async(__change_background_volume_async, NULL);
-
+       g_background_volume->applyVolumeRatio();
        g_is_set_policy = true;
        SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);
-
-       clock_gettime(CLOCK_MONOTONIC, &g_policy_set_time);
-
        SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] set policy for playing");
 
        return;
 }
 
-static Eina_Bool __delay_recover_background_volume(void* data)
-{
-       __recover_background_volume();
-       SLOG(LOG_INFO, tts_tag(), "[BG] Delayed unset policy success");
-
-       g_delayed_unset_policy_timer = NULL;
-       return EINA_FALSE;
-}
-
-static long long int __get_duration_from_last_volume_change()
-{
-       struct timespec current_time;
-       clock_gettime(CLOCK_MONOTONIC, &current_time);
-
-       long long int diff = ((long long int)current_time.tv_sec - (long long int)g_policy_set_time.tv_sec) * 1000
-                       + ((long long int)current_time.tv_nsec - (long long int)g_policy_set_time.tv_nsec) / 1000000;
-       SLOG(LOG_INFO, tts_tag(), "[BG] Time Diff(%lld)", diff);
-
-       return diff;
-}
-
-static void __set_timer_for_delay_recover(void* data)
-{
-       if (NULL != g_delayed_unset_policy_timer) {
-               return;
-       }
-
-       long long int diff = __get_duration_from_last_volume_change();
-       if (diff > SND_MGR_DUCKING_DURATION) {
-               SLOG(LOG_INFO, tts_tag(), "[BG] Direct unset policy");
-               __recover_background_volume();
-       } else {
-               double delay = (double)(SND_MGR_DUCKING_DURATION - diff) / 1000.0;
-               g_delayed_unset_policy_timer = ecore_timer_add(delay, __delay_recover_background_volume, (void*)CHECK_TIMER_DELETE);
-               SLOG(LOG_INFO, tts_tag(), "[BG] Delayed unset policy (%p), delay(%f)", g_delayed_unset_policy_timer, delay);
-       }
-}
-
 static void __unset_policy_for_playing()
 {
        /* Unset stream info */
@@ -554,8 +407,7 @@ static void __unset_policy_for_playing()
                }
        }
 
-       ecore_main_loop_thread_safe_call_async(__set_timer_for_delay_recover, NULL);
-
+       g_background_volume->recoverVolumeRatio();
        g_is_set_policy = false;
        SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);
        SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] unset policy for playing");
@@ -996,44 +848,6 @@ static void __play_thread(void *data, Ecore_Thread *thread)
        }
 }
 
-int __create_ducking_handle(void)
-{
-       int ret = -1;
-       if (NULL == g_media_stream_ducking) {
-               ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_MEDIA, __sound_stream_ducking_state_changed_cb, NULL, &g_media_stream_ducking);
-               if (SOUND_MANAGER_ERROR_NONE != ret)
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to create stream ducking for type media, ret(%d)", ret);
-       } else {
-               SLOG(LOG_INFO, tts_tag(), "[Player INFO] Ducking handle for media stream is already created");
-       }
-
-/*     if (NULL == g_system_stream_ducking) {
-               ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_SYSTEM, __sound_stream_ducking_state_changed_cb, NULL, &g_system_stream_ducking);
-               if (SOUND_MANAGER_ERROR_NONE != ret)
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to create stream ducking for system type, ret(%d)", ret);
-       } else {
-               SLOG(LOG_INFO, tts_tag(), "[Player INFO] Ducking handle for system stream is already created");
-       }
-*/
-       if (NULL == g_notification_stream_ducking) {
-               ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_NOTIFICATION, __sound_stream_ducking_state_changed_cb, NULL, &g_notification_stream_ducking);
-               if (SOUND_MANAGER_ERROR_NONE != ret)
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to create stream ducking for notification type, ret(%d)", ret);
-       } else {
-               SLOG(LOG_INFO, tts_tag(), "[Player INFO] Ducking handle for notification stream is already created");
-       }
-
-       if (NULL == g_alarm_stream_ducking) {
-               ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_ALARM, __sound_stream_ducking_state_changed_cb, NULL, &g_alarm_stream_ducking);
-               if (SOUND_MANAGER_ERROR_NONE != ret)
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to create stream ducking for alarm type, ret(%d)", ret);
-       } else {
-               SLOG(LOG_INFO, tts_tag(), "[Player INFO] Ducking handle for alarm stream is already created");
-       }
-
-       return ret;
-}
-
 /*
 * Player Interfaces
 */
@@ -1069,12 +883,7 @@ int ttsd_player_init()
                SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Create stream info");
        }
 
-       ret = __create_ducking_handle();
-       if (SOUND_MANAGER_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to create ducking handle, ret(%d)", ret);
-       } else {
-               SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Create ducking handle");
-       }
+       g_background_volume = new BackgroundVolume(SND_MGR_DUCKING_DURATION);
 
        ecore_thread_max_set(1);
 
@@ -1089,6 +898,7 @@ int ttsd_player_init()
 
        ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
 
+       g_is_set_policy = false;
        g_player_init = true;
 
        pthread_mutex_unlock(&g_player_control_mutex);
@@ -1096,41 +906,6 @@ int ttsd_player_init()
        return 0;
 }
 
-static void __destroy_all_ducking_handles()
-{
-       SLOG(LOG_INFO, tts_tag(), "[Player] Destroy stream ducking");
-       if (__get_duration_from_last_volume_change() <= SND_MGR_DUCKING_DURATION) {
-               usleep(500000);
-       }
-
-       __recover_background_volume();
-
-       int ret = -1;
-       ret = sound_manager_destroy_stream_ducking(g_media_stream_ducking);
-       if (SOUND_MANAGER_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to destroy ducking handle, ret(%d)", ret);
-       }
-       g_media_stream_ducking = NULL;
-
-/*     ret = sound_manager_destroy_stream_ducking(g_system_stream_ducking);
-       if (SOUND_MANAGER_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to destroy ducking handle, ret(%d)", ret);
-       }
-       g_system_stream_ducking = NULL;
-*/
-       ret = sound_manager_destroy_stream_ducking(g_notification_stream_ducking);
-       if (SOUND_MANAGER_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to destroy ducking handle, ret(%d)", ret);
-       }
-       g_notification_stream_ducking = NULL;
-
-       ret = sound_manager_destroy_stream_ducking(g_alarm_stream_ducking);
-       if (SOUND_MANAGER_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to destroy ducking handle, ret(%d)", ret);
-       }
-       g_alarm_stream_ducking = NULL;
-}
-
 int ttsd_player_release(void)
 {
 #ifdef BUF_SAVE_MODE
@@ -1181,8 +956,6 @@ int ttsd_player_release(void)
                SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Destroy stream info");
        }
 
-       __destroy_all_ducking_handles();
-
        /* clear g_player_list */
        g_playing_info = NULL;
        g_player_init = false;
@@ -1190,6 +963,9 @@ int ttsd_player_release(void)
 
        g_stream_info_h = NULL;
 
+       delete g_background_volume;
+       g_background_volume = nullptr;
+
        pthread_mutex_unlock(&g_player_control_mutex);
 
        return 0;
@@ -1552,47 +1328,12 @@ int ttsd_player_get_background_volume_ratio(double* ratio)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (NULL == ratio)
-               return -1;
-       else
-               *ratio = g_bg_volume_ratio;
-
-       return TTSD_ERROR_NONE;
-}
-
-static Eina_Bool __modify_background_volume_async(void* data)
-{
-       __recover_background_volume();
-       __change_background_volume(0);
-       SLOG(LOG_INFO, tts_tag(), "[BG] Modify background volume with delay");
-
-       g_modify_background_volume = NULL;
-       return EINA_FALSE;
-}
-
-static void __modify_background_volume(void* data)
-{
-       if (NULL != g_delayed_unset_policy_timer) {
-               SLOG(LOG_INFO, tts_tag(), "[BG] Background volume is going to recover soon. Skip modification");
-               return;
-       }
-
-       if (NULL != g_modify_background_volume) {
-               int result = (intptr_t)ecore_timer_del(g_modify_background_volume);
-               g_modify_background_volume = NULL;
-               SLOG(LOG_ERROR, tts_tag(), "[BG] Remove modify background volume timer (%d)", result);
+       if (NULL == ratio) {
+               return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       long long int diff = __get_duration_from_last_volume_change();
-       if (diff > SND_MGR_DUCKING_DURATION) {
-               __recover_background_volume();
-               __change_background_volume(0);
-               SLOG(LOG_INFO, tts_tag(), "[BG] Direct modify background volume");
-       } else {
-               double delay = (double)(SND_MGR_DUCKING_DURATION - diff) / 1000.0;
-               g_modify_background_volume = ecore_timer_add(delay, __modify_background_volume_async, (void*)CHECK_TIMER_DELETE);
-               SLOG(LOG_INFO, tts_tag(), "[BG] Delay modifying background volume (%p), delay(%f)", g_modify_background_volume, delay);
-       }
+       *ratio = g_background_volume->getVolumeRatio();
+       return TTSD_ERROR_NONE;
 }
 
 int ttsd_player_set_background_volume_ratio(double ratio)
@@ -1603,19 +1344,7 @@ int ttsd_player_set_background_volume_ratio(double ratio)
        }
 
        SLOG(LOG_INFO, tts_tag(), "[Player DEBUG] ttsd_player_set_background_volume_ratio : %lf", ratio);
-
-       double prev_ratio = g_bg_volume_ratio;
-       g_bg_volume_ratio = ratio;
-
-       SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Check whether sound is ducked and Change volume. as-is(%lf), to-be(%lf)", prev_ratio, g_bg_volume_ratio);
-       if (prev_ratio == g_bg_volume_ratio) {
-               return TTSD_ERROR_NONE;
-       }
-
-       if (g_is_set_policy) {
-               SLOG(LOG_INFO, tts_tag(), "[BG] Direct modify background volume");
-               ecore_main_loop_thread_safe_call_async(__modify_background_volume, NULL);
-       }
+       g_background_volume->setVolumeRatio(ratio);
 
        return TTSD_ERROR_NONE;
 }
index 1931fe9..04d9a70 100644 (file)
@@ -493,6 +493,12 @@ int ttsd_initialize(ttse_request_callback_s *callback)
                SLOG(LOG_ERROR, tts_tag(), "[Server WARNING] Fail to initialize config.");
        }
 
+       /* player init */
+       if (ttsd_player_init()) {
+               SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to initialize player init.");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
        double ratio;
        if (0 == ttsd_config_get_bg_volume_ratio(&ratio))
        {
@@ -500,14 +506,8 @@ int ttsd_initialize(ttse_request_callback_s *callback)
                int ret = ttsd_player_set_background_volume_ratio(ratio);
                if (0 != ret)
                        SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to set bg volume ratio : result(%d)", ret);
-       }
-       else
+       } else {
                SLOG(LOG_ERROR, tts_tag(), "[Server WARNING] Fail to get bg volume ratio");
-
-       /* player init */
-       if (ttsd_player_init()) {
-               SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to initialize player init.");
-               return TTSD_ERROR_OPERATION_FAILED;
        }
 
        /* Engine Agent initialize */