--- /dev/null
+/*
+* 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;
+}
--- /dev/null
+/*
+* 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_ */
ttse.c
ttsd_network.c
ttsd_player.cpp
+ BackgroundVolume.cpp
ttsd_server.c
../common/tts_config_mgr.c
../common/tts_config_parser.c
#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"
#include "ttsd_dbus.h"
#include "ttsd_ipc.h"
+#include "BackgroundVolume.h"
+
#include "tts_internal.h"
#include "ttsd_server.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
*/
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;
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()) {
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, ¤t_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 */
}
}
- 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");
}
}
-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
*/
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);
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);
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
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;
g_stream_info_h = NULL;
+ delete g_background_volume;
+ g_background_volume = nullptr;
+
pthread_mutex_unlock(&g_player_control_mutex);
return 0;
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)
}
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;
}
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))
{
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 */