From 75a317c615b282f921bc949c654e0f0824929583 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Wed, 10 Aug 2022 21:11:22 +0900 Subject: [PATCH] Add new class for managing state of server - Requirement: The TTS engine library needs to manage its state. - Solution: This patch adds new class StateManager which helps to manage state of TTS service. Through this new class, the TTS engine library can easily change the state and notify it. Change-Id: I3fe6a38fcd9f55f8027b8ed1cdec8ca453cbe9a8 Signed-off-by: Suyeon Hwang --- server/CMakeLists.txt | 1 + server/StateManager.h | 44 +++++++++++++++++ server/ttsd_main.h | 7 +++ server/ttsd_player.cpp | 11 +++++ server/ttsd_server.c | 10 ++++ server/ttsd_state.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ server/ttsd_state.h | 41 ++++++++++++++++ 7 files changed, 239 insertions(+) create mode 100644 server/StateManager.h create mode 100644 server/ttsd_state.cpp create mode 100644 server/ttsd_state.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 706021a..144da80 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -14,6 +14,7 @@ SET(SRCS PlayerThread.cpp ActivatedModes.cpp ttsd_server.c + ttsd_state.cpp ../common/tts_config_mgr.c ../common/tts_config_parser.c ) diff --git a/server/StateManager.h b/server/StateManager.h new file mode 100644 index 0000000..eb8ddf2 --- /dev/null +++ b/server/StateManager.h @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2022 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_STATE_MANAGER_H_ +#define __TTSD_STATE_MANAGER_H_ + + +#include + +#include "ttsd_state.h" + + +class StateManager { +public: + StateManager(ttsd_state_changed_cb callback); + ~StateManager(); + + ttsd_state_e getState(); + void setState(ttsd_state_e state); + +private: + static void notifyStateChangeOnMainThread(void* data); + +private: + ttsd_state_e __beforeState; + ttsd_state_e __currentState; + std::mutex __stateMutex; + + ttsd_state_changed_cb __callback; +}; + +#endif /* __TTSD_STATE_MANAGER_H_ */ diff --git a/server/ttsd_main.h b/server/ttsd_main.h index d35def8..40e886c 100644 --- a/server/ttsd_main.h +++ b/server/ttsd_main.h @@ -65,6 +65,13 @@ typedef enum { TTSD_INTERRUPTED_STOPPED /**< Current state change 'Ready' */ } ttsd_interrupted_code_e; +typedef enum { + TTSD_STATE_INVALID = -1, + TTSD_STATE_READY = 0, /**< 'Idle' state */ + TTSD_STATE_SYNTHESIZING = 1, /**< 'Synthesizing' state */ + TTSD_STATE_PLAYING = 2 /**< 'Playing' state */ +} ttsd_state_e; + typedef struct { char* engine_id; char* engine_name; diff --git a/server/ttsd_player.cpp b/server/ttsd_player.cpp index e2aa2e2..a2198d4 100644 --- a/server/ttsd_player.cpp +++ b/server/ttsd_player.cpp @@ -15,6 +15,7 @@ #include "ttsd_data.h" #include "ttsd_ipc.h" #include "ttsd_player.h" +#include "ttsd_state.h" #include "BackgroundVolume.h" #include "AudioStream.h" @@ -59,6 +60,16 @@ static void __set_playing_status(bool is_playing) { int ret = vconf_set_bool(TTS_PLAYING_STATUS_KEY, is_playing ? 1 : 0); SLOG(LOG_INFO, tts_tag(), "[Player] Set playing status (%s). ret(%d)", is_playing ? "True" : "False", ret); + + if (is_playing) { + ttsd_state_set_state(TTSD_STATE_PLAYING); + } else { + if (ttsd_data_get_synth_control() == TTSD_SYNTHESIS_CONTROL_DOING) { + ttsd_state_set_state(TTSD_STATE_SYNTHESIZING); + } else { + ttsd_state_set_state(TTSD_STATE_READY); + } + } } #ifdef BUF_SAVE_MODE diff --git a/server/ttsd_server.c b/server/ttsd_server.c index f515c33..4887875 100644 --- a/server/ttsd_server.c +++ b/server/ttsd_server.c @@ -22,6 +22,7 @@ #include "ttsd_engine_agent.h" #include "ttsd_main.h" #include "ttsd_player.h" +#include "ttsd_state.h" #include "ttsd_server.h" @@ -159,6 +160,10 @@ static void __synthesis(unsigned int uid) g_wait_timer = ecore_timer_add(0.05, __wait_synthesis, (void*)credential); } + if (ttsd_data_get_synth_control() == TTSD_SYNTHESIS_CONTROL_DOING && ttsd_state_get_state() == TTSD_STATE_READY) { + ttsd_state_set_state(TTSD_STATE_SYNTHESIZING); + } + free(credential); credential = NULL; ttsd_data_destroy_speak_data(speak_data); @@ -556,6 +561,10 @@ int ttsd_initialize(ttse_request_callback_s *callback) SLOG(LOG_ERROR, tts_tag(), "[Server WARNING] Fail to initialize config."); } + if (TTSD_ERROR_NONE != ttsd_state_initialize(NULL)) { + SLOG(LOG_ERROR, tts_tag(), "[Server WARNING] Fail to initialize state."); + } + /* player init */ if (ttsd_player_init()) { SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to initialize player init."); @@ -625,6 +634,7 @@ int ttsd_finalize() } ttsd_config_finalize(); + ttsd_state_finalize(); int ret = TTSD_ERROR_NONE; ret = ttsd_player_release(); diff --git a/server/ttsd_state.cpp b/server/ttsd_state.cpp new file mode 100644 index 0000000..14e9f4c --- /dev/null +++ b/server/ttsd_state.cpp @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2022 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 + +#include "StateManager.h" +#include "ttsd_state.h" + + +using namespace std; + + +static StateManager* g_stateManager = nullptr; + +StateManager::StateManager(ttsd_state_changed_cb callback) : + __beforeState(TTSD_STATE_READY), __currentState(TTSD_STATE_READY), __callback(callback) +{ + SLOG(LOG_INFO, tts_tag(), "[StateManager] Constructor"); +} + +StateManager::~StateManager() +{ + SLOG(LOG_INFO, tts_tag(), "[StateManager] Destructor"); + __beforeState = TTSD_STATE_READY; + __currentState = TTSD_STATE_READY; + __callback = nullptr; +} + +ttsd_state_e StateManager::getState() +{ + lock_guard lock(__stateMutex); + return __currentState; +} + +void StateManager::setState(ttsd_state_e state) +{ + unique_lock lock(__stateMutex); + __beforeState = __currentState; + __currentState = state; + + if (__beforeState == __currentState) { + return; + } + + SLOG(LOG_INFO, tts_tag(), "[StateManager] StateManager is changed. (%d) -> (%d)", __beforeState, __currentState); + lock.unlock(); + ecore_main_loop_thread_safe_call_async(notifyStateChangeOnMainThread, static_cast(this)); +} + +void StateManager::notifyStateChangeOnMainThread(void* data) +{ + if (nullptr == data) { + SLOG(LOG_ERROR, tts_tag(), "[StateManager] Invalid data is passed"); + return; + } + + StateManager* stateManager = static_cast(data); + + unique_lock lock(stateManager->__stateMutex); + ttsd_state_e before = stateManager->__beforeState; + ttsd_state_e current = stateManager->__currentState; + lock.unlock(); + + if (stateManager->__callback) { + stateManager->__callback(before, current); + } +} + + +int ttsd_state_initialize(ttsd_state_changed_cb callback) +{ + g_stateManager = new(nothrow) StateManager(callback); + + if (nullptr == g_stateManager) { + SLOG(LOG_ERROR, tts_tag(), "[StateManager] Fail to initialize StateManager"); + return TTSD_ERROR_OUT_OF_MEMORY; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_state_finalize() +{ + if (nullptr == g_stateManager) { + SLOG(LOG_ERROR, tts_tag(), "[StateManager] StateManager is not initialized"); + return TTSD_ERROR_INVALID_STATE; + } + + delete g_stateManager; + g_stateManager = nullptr; + + return TTSD_ERROR_NONE; +} + +int ttsd_state_set_state(ttsd_state_e state) +{ + if (nullptr == g_stateManager) { + SLOG(LOG_ERROR, tts_tag(), "[StateManager] StateManager is not initialized"); + return TTSD_ERROR_INVALID_STATE; + } + + g_stateManager->setState(state); + return TTSD_ERROR_NONE; +} + +ttsd_state_e ttsd_state_get_state() +{ + if (nullptr == g_stateManager) { + SLOG(LOG_ERROR, tts_tag(), "[StateManager] StateManager is not initialized"); + return TTSD_STATE_INVALID; + } + + return g_stateManager->getState(); +} diff --git a/server/ttsd_state.h b/server/ttsd_state.h new file mode 100644 index 0000000..b03506d --- /dev/null +++ b/server/ttsd_state.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2022 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_STATE_H__ +#define __TTSD_STATE_H__ + +#include "ttsd_main.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef void (*ttsd_state_changed_cb)(ttsd_state_e before, ttsd_state_e current); + + +int ttsd_state_initialize(ttsd_state_changed_cb callback); + +int ttsd_state_finalize(); + +int ttsd_state_set_state(ttsd_state_e state); + +ttsd_state_e ttsd_state_get_state(); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_STATE_H__ */ -- 2.7.4