From 0f6ac38f1505456484dd16f18dc8c4615131512e Mon Sep 17 00:00:00 2001 From: Kibum Kim Date: Mon, 27 Feb 2012 21:16:45 +0900 Subject: [PATCH 1/1] tizen beta release --- AUTHORS | 2 + CMakeLists.txt | 17 + COPYING | 10 + client/CMakeLists.txt | 66 ++ client/tts-setting.pc.in | 11 + client/tts.c | 863 ++++++++++++++++++++++++ client/tts.h | 487 +++++++++++++ client/tts.pc.in | 11 + client/tts_client.c | 189 ++++++ client/tts_client.h | 68 ++ client/tts_dbus.c | 732 ++++++++++++++++++++ client/tts_dbus.h | 51 ++ client/tts_main.h | 46 ++ client/tts_setting.c | 542 +++++++++++++++ client/tts_setting.h | 317 +++++++++ client/tts_setting_dbus.c | 909 +++++++++++++++++++++++++ client/tts_setting_dbus.h | 58 ++ common/tts_defs.h | 86 +++ debian/changelog | 7 + debian/compat | 1 + debian/control | 25 + debian/copyright | 12 + debian/dirs | 2 + debian/docs | 3 + debian/libtts-dev.install.in | 5 + debian/libtts.install.in | 2 + debian/rules | 137 ++++ packaging/tts.spec | 68 ++ server/CMakeLists.txt | 68 ++ server/ttsd_config.c | 222 ++++++ server/ttsd_config.h | 62 ++ server/ttsd_data.cpp | 433 ++++++++++++ server/ttsd_data.h | 107 +++ server/ttsd_dbus.c | 333 +++++++++ server/ttsd_dbus.h | 43 ++ server/ttsd_dbus_server.c | 1302 +++++++++++++++++++++++++++++++++++ server/ttsd_dbus_server.h | 87 +++ server/ttsd_engine_agent.c | 1538 ++++++++++++++++++++++++++++++++++++++++++ server/ttsd_engine_agent.h | 107 +++ server/ttsd_main.c | 67 ++ server/ttsd_main.h | 80 +++ server/ttsd_network.c | 95 +++ server/ttsd_network.h | 34 + server/ttsd_player.cpp | 990 +++++++++++++++++++++++++++ server/ttsd_player.h | 62 ++ server/ttsd_server.cpp | 958 ++++++++++++++++++++++++++ server/ttsd_server.h | 92 +++ server/ttsp.h | 379 +++++++++++ 48 files changed, 11786 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 client/CMakeLists.txt create mode 100644 client/tts-setting.pc.in create mode 100644 client/tts.c create mode 100644 client/tts.h create mode 100644 client/tts.pc.in create mode 100644 client/tts_client.c create mode 100644 client/tts_client.h create mode 100644 client/tts_dbus.c create mode 100644 client/tts_dbus.h create mode 100644 client/tts_main.h create mode 100644 client/tts_setting.c create mode 100644 client/tts_setting.h create mode 100644 client/tts_setting_dbus.c create mode 100644 client/tts_setting_dbus.h create mode 100644 common/tts_defs.h create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/libtts-dev.install.in create mode 100644 debian/libtts.install.in create mode 100755 debian/rules create mode 100644 packaging/tts.spec create mode 100644 server/CMakeLists.txt create mode 100644 server/ttsd_config.c create mode 100644 server/ttsd_config.h create mode 100644 server/ttsd_data.cpp create mode 100644 server/ttsd_data.h create mode 100644 server/ttsd_dbus.c create mode 100644 server/ttsd_dbus.h create mode 100644 server/ttsd_dbus_server.c create mode 100644 server/ttsd_dbus_server.h create mode 100644 server/ttsd_engine_agent.c create mode 100644 server/ttsd_engine_agent.h create mode 100644 server/ttsd_main.c create mode 100644 server/ttsd_main.h create mode 100644 server/ttsd_network.c create mode 100644 server/ttsd_network.h create mode 100644 server/ttsd_player.cpp create mode 100644 server/ttsd_player.h create mode 100644 server/ttsd_server.cpp create mode 100644 server/ttsd_server.h create mode 100644 server/ttsp.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..cd12545 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Dongyeol Lee +Sehwan Park \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d8e146c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(libtts) + +## Include common directory ## +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/common") + +## Dependent packages ## +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + mm-player vconf dlog ecore openssl dbus-1 +) + +## Client library ## +ADD_SUBDIRECTORY(client) + +## Server daemon ## +ADD_SUBDIRECTORY(server) diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..bf8fbd7 --- /dev/null +++ b/COPYING @@ -0,0 +1,10 @@ +Copyright (c) 2011 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. diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000..c97a1dd --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,66 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(tts C) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}") +SET(LIBDIR "${PREFIX}/lib") +SET(INCLUDEDIR "${PREFIX}/include") +SET(VERSION 0.1.1) + +SET(SRCS + tts.c + tts_client.c + tts_dbus.c +) + +SET(SETTING_SRCS + tts_setting.c + tts_setting_dbus.c +) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${INCLUDEDIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../common) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + glib-2.0 dbus-1 dlog ecore +) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF ("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET_ARM") + MESSAGE("[TARGET] Compile") +ELSE ("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET_I386") + MESSAGE("[i386] Compile") +ENDIF ("${ARCH}" STREQUAL "arm") + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +## Add definitions ## +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") + +## TTS library ## +ADD_LIBRARY("${PROJECT_NAME}_static" STATIC ${SRCS}) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +## TTS-setting library ## +ADD_LIBRARY("${PROJECT_NAME}_setting" SHARED ${SETTING_SRCS}) +TARGET_LINK_LIBRARIES("${PROJECT_NAME}_setting" ${pkgs_LDFLAGS}) + +## configure pkgconfig files ## +CONFIGURE_FILE(tts.pc.in "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc" @ONLY) +CONFIGURE_FILE(tts-setting.pc.in "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}-setting.pc" @ONLY) + +## Install library files ## +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) +INSTALL(TARGETS ${PROJECT_NAME}_setting DESTINATION lib COMPONENT RuntimeLibraries) +INSTALL(FILES "${PROJECT_NAME}.pc" "${PROJECT_NAME}-setting.pc" DESTINATION lib/pkgconfig) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tts.h ${CMAKE_CURRENT_SOURCE_DIR}/tts_setting.h DESTINATION include) diff --git a/client/tts-setting.pc.in b/client/tts-setting.pc.in new file mode 100644 index 0000000..0946661 --- /dev/null +++ b/client/tts-setting.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: lib@PROJECT_NAME@_setting +Description: Text To Speech client library +Requires: glib-2.0 dbus-1 +Version: @VERSION@ +Libs: -L${libdir} -l@PROJECT_NAME@_setting +Cflags: -I${includedir} diff --git a/client/tts.c b/client/tts.c new file mode 100644 index 0000000..1ff1576 --- /dev/null +++ b/client/tts.c @@ -0,0 +1,863 @@ +/* +* Copyright (c) 2011 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 "tts_main.h" +#include "tts_client.h" +#include "tts_dbus.h" + +#define MAX_TEXT_COUNT 1000 +#define CONNECTION_RETRY_COUNT 3 + +/* Function definition */ +int __tts_check_tts_daemon(); + +int tts_create(tts_h* tts) +{ + int ret = 0; + + SLOG(LOG_DEBUG, TAG_TTSC, "===== Create TTS"); + + /* check param */ + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + /* Check daemon is running */ + __tts_check_tts_daemon(); + + if (0 == tts_client_get_size()) { + if (0 != tts_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to open dbus connection\n "); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_OPERATION_FAILED; + } + } + + if (0 != tts_client_new(tts)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create client!!!!!"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_OUT_OF_MEMORY; + } + + /* do request initialize */ + int i = 0; + while(1) { + ret = tts_dbus_request_initialize((*tts)->handle); + + if (TTS_ERROR_ENGINE_NOT_FOUND == ret) { + tts_client_destroy(*tts); + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine not found"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return ret; + } else if( ret ) { + sleep(1); + if (i == CONNECTION_RETRY_COUNT) { + tts_client_destroy(*tts); + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Connection Time out"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_TIMED_OUT; + } + i++; + } else { + /* success to connect tts-daemon */ + break; + } + } + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] uid(%d)", (*tts)->handle); + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_ERROR_NONE; +} + +int tts_destroy(tts_h tts) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Destroy TTS"); + + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + /* check handle */ + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + /* Request Finalize */ + int ret = tts_dbus_request_finalize(client->uid); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request finalize "); + } + + /* Free resources */ + tts_client_destroy(tts); + + if (0 == tts_client_get_size()) { + if (0 != tts_dbus_close_connection()) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to close connection\n "); + } + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_ERROR_NONE; +} + +int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported voices"); + + if (NULL == tts || NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + /* check handle */ + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "Current state is NOT 'READY'.\n"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_STATE; + } + + int ret = 0; + ret = tts_dbus_request_get_support_voice(client->uid, client->tts, callback, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_get_default_voice(tts_h tts, char** lang, tts_voice_type_e* vctype) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default voice"); + + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + + } + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Current state is NOT 'READY'. "); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_STATE; + } + + /* Request call remote method */ + int ret = 0; + ret = tts_dbus_request_get_default_voice(client->uid, lang, vctype ); + + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_get_max_text_count(tts_h tts, int* count) +{ + if (NULL == tts || NULL == count) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : Current state is NOT 'READY'."); + return TTS_ERROR_INVALID_STATE; + } + + *count = MAX_TEXT_COUNT; + + SLOG(LOG_DEBUG, TAG_TTSC, "[Suceess] Get max text count"); + return TTS_ERROR_NONE; +} + +int tts_get_state(tts_h tts, tts_state_e* state) +{ + if (NULL == tts || NULL == state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + *state = client->current_state; + + switch(*state) { + case TTS_STATE_READY: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Ready'"); break; + case TTS_STATE_PLAYING: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Playing'"); break; + case TTS_STATE_PAUSED: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Paused'"); break; + } + + return TTS_ERROR_NONE; +} + +int tts_add_text(tts_h tts, const char* text, const char* language, tts_voice_type_e voice_type, tts_speed_e speed, int* utt_id) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Add text"); + + if (NULL == tts || NULL == utt_id) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + /* change default language value */ + char* temp = NULL; + + if (NULL == language) + temp = strdup("default"); + else + temp = strdup(language); + + client->current_utt_id ++; + if (client->current_utt_id == 10000) { + client->current_utt_id = 1; + } + + /* do request */ + int ret = 0; + ret = tts_dbus_request_add_text(client->uid, text, temp, voice_type, speed, client->current_utt_id); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + } + + *utt_id = client->current_utt_id; + + if (NULL != temp) + free(temp); + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_play(tts_h tts) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Play tts"); + + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_PLAYING == client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "Current state is 'playing'. This request should be skipped.\n"); + return TTS_ERROR_INVALID_STATE; + } + + int ret = 0; + ret = tts_dbus_request_play(client->uid); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return ret; + } + + /* change state */ + client->current_state = TTS_STATE_PLAYING; + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_ERROR_NONE; +} + + +int tts_stop(tts_h tts) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Stop tts"); + + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + SLOG(LOG_DEBUG, TAG_TTSC, "change state to ready\n"); + client->current_state = TTS_STATE_READY; + + int ret = 0; + ret = tts_dbus_request_stop(client->uid); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return ret; + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_ERROR_NONE; +} + + +int tts_pause(tts_h tts) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Pause tts"); + + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_PLAYING != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "Error : Current state is NOT 'playing'. So this request should be not running.\n"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_ERROR_INVALID_STATE; + } + + int ret = 0; + ret = tts_dbus_request_pause(client->uid); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return ret; + } + + client->current_state = TTS_STATE_PAUSED; + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_ERROR_NONE; +} + +int __tts_cb_error(int uid, tts_error_e reason, int utt_id) +{ + tts_client_s* client = tts_client_get_by_uid(uid); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + /* call callback function */ + if (NULL != client->error_cb) { + SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of error"); + tts_client_use_callback(client); + client->error_cb(client->tts, utt_id, reason, client->error_user_data ); + tts_client_not_use_callback(client); + } else { + SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of error \n"); + } + + return 0; +} + +int __tts_cb_interrupt(int uid, tts_interrupted_code_e code) +{ + tts_client_s* client = tts_client_get_by_uid(uid); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + /* change state by interrupt code */ + if (TTS_INTERRUPTED_PAUSED == code) { + SLOG(LOG_DEBUG, TAG_TTSC, "change state to ready"); + client->current_state = TTS_STATE_PAUSED; + } else if (TTS_INTERRUPTED_STOPPED == code) { + SLOG(LOG_DEBUG, TAG_TTSC, "change state to ready"); + client->current_state = TTS_STATE_READY; + } else { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Interrupt code is not available"); + return -1; + } + + /* call callback function */ + if (NULL != client->interrupted_cb) { + SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of stopped \n"); + tts_client_use_callback(client); + client->interrupted_cb(client->tts, code, client->interrupted_user_data); + tts_client_not_use_callback(client); + } else { + SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of stopped \n"); + } + + return 0; +} + +int __tts_cb_utt_started(int uid, int utt_id) +{ + tts_client_s* client = tts_client_get_by_uid(uid); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + SLOG(LOG_DEBUG, TAG_TTSC, "utterance started : uttid(%d) \n", utt_id); + + /* call callback function */ + if (NULL != client->utt_started_cb) { + SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance started \n"); + tts_client_use_callback(client); + client->utt_started_cb(client->tts, utt_id, client->utt_started_user_data); + tts_client_not_use_callback(client); + } else { + SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance started \n"); + } + + return 0; +} + +int __tts_cb_utt_completed(int uid, int utt_id) +{ + tts_client_s* client = tts_client_get_by_uid(uid); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + SLOG(LOG_DEBUG, TAG_TTSC, "utterance completed : uttid(%d) \n", utt_id); + + /* call callback function */ + if (NULL != client->utt_completeted_cb) { + SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance completed \n"); + tts_client_use_callback(client); + client->utt_completeted_cb(client->tts, utt_id, client->utt_completed_user_data); + tts_client_not_use_callback(client); + } else { + SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance completed \n"); + } + + return 0; +} + +int tts_set_interrupted_cb(tts_h tts, tts_interrupted_cb callback, void* user_data) +{ + if (NULL == tts || NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set interrupted cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set interrupted cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set interrupted cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->interrupted_cb = callback; + client->interrupted_user_data = user_data; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set interrupted cb"); + + return 0; +} + +int tts_unset_interrupted_cb(tts_h tts) +{ + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset interrupted cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset interrupted cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset interrupted cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->interrupted_cb = NULL; + client->interrupted_user_data = NULL; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset interrupted cb"); + + return 0; +} + +int tts_set_utterance_started_cb(tts_h tts, tts_utterance_started_cb callback, void* user_data) +{ + if (NULL == tts || NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt started cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->utt_started_cb = callback; + client->utt_started_user_data = user_data; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set utt started cb"); + + return 0; +} + +int tts_unset_utterance_started_cb(tts_h tts) +{ + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt started cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt started cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt started cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->utt_started_cb = NULL; + client->utt_started_user_data = NULL; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset utt started cb"); + + return 0; +} + +int tts_set_utterance_completed_cb(tts_h tts, tts_utterance_completed_cb callback, void* user_data) +{ + if (NULL == tts || NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt completed cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt completed cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set utt completed cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->utt_completeted_cb = callback; + client->utt_completed_user_data = user_data; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set utt completed cb"); + + return 0; +} + +int tts_unset_utterance_completed_cb(tts_h tts) +{ + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt completed cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt completed cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset utt completed cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->utt_completeted_cb = NULL; + client->utt_completed_user_data = NULL; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset utt completed cb"); + return 0; +} + +int tts_set_error_cb(tts_h tts, tts_error_cb callback, void* user_data) +{ + if (NULL == tts || NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set error cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set error cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Set error cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->error_cb = callback; + client->error_user_data = user_data; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set error cb"); + + return 0; +} + +int tts_unset_error_cb(tts_h tts) +{ + if (NULL == tts) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset error cb : Input parameter is null"); + return TTS_ERROR_INVALID_PARAMETER; + } + + tts_client_s* client = tts_client_get(tts); + + if (NULL == client) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset error cb : A handle is not valid"); + return TTS_ERROR_INVALID_PARAMETER; + } + + if (TTS_STATE_READY != client->current_state) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Unset error cb : Current state is not 'ready'."); + return TTS_ERROR_INVALID_STATE; + } + + client->error_cb = NULL; + client->error_user_data = NULL; + + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset error cb"); + + return 0; +} + +static bool _tts_is_alive() +{ + FILE *fp = NULL; + char buff[256]; + char cmd[256]; + int i=0; + + memset(buff, 0, sizeof(char)); + memset(cmd, 0, sizeof(char)); + + if ((fp = popen("ps -eo \"cmd\"", "r")) == NULL) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] popen error \n"); + return FALSE; + } + + while(fgets(buff, 255, fp)) { + if (0 == i) { + i++; + continue; + } + + sscanf(buff, "%s", cmd); + + if (0 == strncmp(cmd, "[tts-daemon]", strlen("[tts-daemon]")) || + 0 == strncmp(cmd, "tts-daemon", strlen("tts-daemon")) || + 0 == strncmp(cmd, "/usr/bin/tts-daemon", strlen("/usr/bin/tts-daemon"))) { + SLOG(LOG_DEBUG, TAG_TTSC, "tts-daemon is ALIVE !! \n"); + fclose(fp); + return TRUE; + } + + i++; + } + fclose(fp); + + return FALSE; +} + + +static void __my_sig_child(int signo, siginfo_t *info, void *data) +{ + int status; + pid_t child_pid, child_pgid; + + child_pgid = getpgid(info->si_pid); + SLOG(LOG_DEBUG, TAG_TTSC, "Signal handler: dead pid = %d, pgid = %d\n", info->si_pid, child_pgid); + + while (0 < (child_pid = waitpid(-1, &status, WNOHANG))) { + if(child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + } + + return; +} + +int __tts_check_tts_daemon() +{ + if (TRUE == _tts_is_alive()) + return 0; + + /* fork-exec tts-daemom */ + SLOG(LOG_DEBUG, TAG_TTSC, "THERE IS NO tts-daemon \n"); + SLOG(LOG_DEBUG, TAG_TTSC, "START TTS-DAEMON \n"); + + int pid, i; + struct sigaction act, dummy; + + act.sa_handler = NULL; + act.sa_sigaction = __my_sig_child; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; + + if (sigaction(SIGCHLD, &act, &dummy) < 0) { + SLOG(LOG_ERROR, TAG_TTSC, "Cannot make a signal handler"); + return -1; + } + + pid = fork(); + + switch(pid) { + case -1: + SLOG(LOG_ERROR, TAG_TTSC, "fail to create TTS-DAEMON \n"); + break; + + case 0: + setsid(); + for (i = 0;i < _NSIG;i++) + signal(i, SIG_DFL); + + execl("/usr/bin/tts-daemon", "/usr/bin/tts-daemon", NULL); + break; + + default: + sleep(1); + break; + } + + return 0; +} diff --git a/client/tts.h b/client/tts.h new file mode 100644 index 0000000..6ce02b7 --- /dev/null +++ b/client/tts.h @@ -0,0 +1,487 @@ +/* +* Copyright (c) 2011 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 __TTS_H__ +#define __TTS_H__ + +#include +#include + +/** +* @addtogroup CAPI_UIX_TTS_MODULE +* @{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief Enumerations of error codes. +*/ +typedef enum { + TTS_ERROR_NONE = 0, /**< Successful */ + TTS_ERROR_OUT_OF_MEMORY = -ENOMEM, /**< Out of Memory */ + TTS_ERROR_IO_ERROR = -EIO, /**< I/O error */ + TTS_ERROR_INVALID_PARAMETER = -EINVAL, /**< Invalid parameter */ + TTS_ERROR_OUT_OF_NETWORK = -ENETDOWN, /**< Out of network */ + TTS_ERROR_INVALID_STATE = -0x0100021, /**< Invalid state */ + TTS_ERROR_INVALID_VOICE = -0x0100022, /**< Invalid voice */ + TTS_ERROR_ENGINE_NOT_FOUND = -0x0100023, /**< No available engine */ + TTS_ERROR_TIMED_OUT = -0x0100024, /**< No answer from the daemon */ + TTS_ERROR_OPERATION_FAILED = -0x0100025 /**< Operation failed */ +} tts_error_e; + +/** +* @brief Enumerations of speaking speed. +*/ +typedef enum { + TTS_SPEED_AUTO, /**< Speed from settings */ + TTS_SPEED_VERY_SLOW, /**< Very slow */ + TTS_SPEED_SLOW, /**< Slow */ + TTS_SPEED_NORMAL, /**< Normal */ + TTS_SPEED_FAST, /**< Fast */ + TTS_SPEED_VERY_FAST /**< Very fast */ +} tts_speed_e; + +/** +* @brief Enumerations of voice type. +*/ +typedef enum { + TTS_VOICE_TYPE_AUTO, /**< Voice type from settings or auto selection based language */ + TTS_VOICE_TYPE_MALE, /**< Male */ + TTS_VOICE_TYPE_FEMALE, /**< Female */ + TTS_VOICE_TYPE_CHILD, /**< Child */ + TTS_VOICE_TYPE_USER1, /**< Engine defined */ + TTS_VOICE_TYPE_USER2, /**< Engine defined */ + TTS_VOICE_TYPE_USER3 /**< Engine defined */ +} tts_voice_type_e; + +/** +* @brief Enumerations of interrupted code. +*/ +typedef enum { + TTS_INTERRUPTED_PAUSED = 0, /**< The current state be changed #TTS_STATE_PAUSED by the daemon */ + TTS_INTERRUPTED_STOPPED /**< The current state be changed #TTS_STATE_READY by the daemon */ +} tts_interrupted_code_e; + +/** +* @brief Enumerations of state. +*/ +typedef enum { + TTS_STATE_READY = 0, /**< 'READY' state */ + TTS_STATE_PLAYING, /**< 'PLAYING' state */ + TTS_STATE_PAUSED /**< 'PAUSED' state*/ +}tts_state_e; + +/** +* @brief A structure of handle for identification +*/ +typedef struct tts_s *tts_h; + + +/** +* @brief Called when the TTS state has changed by the daemon. +* +* @details If the daemon must stop player because of changing engine and +* the daemon must pause player because of other requests, this callback function is called. +* +* @param[in] tts The handle for TTS +* @param[in] code The interrupt type +* @param[in] user_data The user data passed from the the callback registration function +* +* @pre An application registers this callback using tts_set_interrupted_cb() to detect interrupts. +* @post If this function is called, the TTS state will be #TTS_STATE_READY or #TTS_STATE_PAUSED. +* +* @see tts_set_interrupted_cb() +* @see tts_unset_interrupted_cb() +*/ +typedef void (*tts_interrupted_cb)(tts_h tts, tts_interrupted_code_e code, void* user_data); + +/** +* @brief Called when utterance has started. +* +* @param[in] tts The handle for TTS +* @param[in] utt_id The utterance ID passed from the add text function +* @param[in] user_data The user data passed from the callback registration function +* +* @pre An application registers this callback using tts_set_utterance_started_cb() to detect utterance started. +* +* @see tts_add_text() +* @see tts_set_utterance_started_cb() +* @see tts_unset_utterance_started_cb() +*/ +typedef void (*tts_utterance_started_cb)(tts_h tts, int utt_id, void* user_data); + +/** +* @brief Called when utterance is finished. +* +* @param[in] tts The handle for TTS +* @param[in] utt_id The utterance ID passed from the add text function +* @param[in] user_data The user data passed from from the callback registration function +* +* @pre An application registers this callback using tts_set_utterance_completed_cb() to detect utterance completed. +* +* @see tts_add_text() +* @see tts_set_utterance_completed_cb() +* @see tts_unset_utterance_completed_cb() +*/ +typedef void (*tts_utterance_completed_cb)(tts_h tts, int utt_id, void *user_data); + +/** +* @brief Called when error occurred. +* +* @param[in] tts The handle for TTS +* @param[in] utt_id The utterance ID passed from the add text function +* @param[in] reason The error code +* @param[in] user_data The user data passed from the callback registration function +* +* @pre An application registers this callback using tts_set_error_cb() to detect error. +* +* @see tts_play() +* @see tts_pause() +* @see tts_stop() +* @see tts_set_error_cb() +* @see tts_unset_error_cb() +*/ +typedef void (*tts_error_cb)(tts_h tts, int utt_id, tts_error_e reason, void* user_data); + +/** +* @brief Called to retrieve the supported voice. +* +* @param[in] tts The handle for TTS +* @param[in] language A language is specified as an ISO 3166 alpha-2 two letter country-code \n +* followed by ISO 639-1 for the two-letter language code. \n +* For example, "ko_KR" for Korean, "en_US" for American English +* @param[in] voice_type A voice type +* @param[in] user_data The user data passed from the foreach function +* +* @return @c true to continue with the next iteration of the loop \n @c false to break out of the loop +* @pre tts_foreach_supported_voices() will invoke this callback. +* +* @see tts_foreach_supported_voices() +*/ +typedef bool(*tts_supported_voice_cb)(tts_h tts, const char* language, tts_voice_type_e voice_type, void* user_data); + +/** +* @brief Creates a handle for TTS and connects the daemon. +* +* @param[out] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_TIMED_OUT The daemon is blocked or do not exist +* @retval #TTS_ERROR_ENGINE_NOT_FOUND No available engine \n Engine should be installed +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_OUT_OF_MEMORY Out of memory +* +* @see tts_destroy() +*/ +int tts_create(tts_h* tts); + +/** +* @brief Destroys the handle and disconnects the daemon. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_create() +*/ +int tts_destroy(tts_h tts); + +/** +* @brief Retrieves all supported voices of the current engine using callback function. +* +* @param[in] tts The handle for TTS +* @param[in] callback The callback function to invoke +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* @post This function invokes tts_supported_voice_cb() repeatedly for getting voices. +* +* @see tts_get_default_voice() +*/ +int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, void* user_data); + +/** +* @brief Gets the default voice set by user. +* +* @remark If the function succeeds, @a language must be released with free() by you. +* +* @param[in] tts The handle for TTS +* @param[out] language A language is specified as an ISO 3166 alpha-2 two letter country-code \n +* followed by ISO 639-1 for the two-letter language code. \n +* For example, "ko_KR" for Korean, "en_US" for American English. +* @param[out] voice_type The voice type +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_OUT_OF_MEMORY Out of memory +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @see tts_foreach_supported_voices() +*/ +int tts_get_default_voice(tts_h tts, char** language, tts_voice_type_e* voice_type); + +/** +* @brief Gets the maximum text count of a current engine. +* +* @param[in] tts The handle for TTS +* @param[out] count The maximum text count of the current engine +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @see tts_add_text() +*/ +int tts_get_max_text_count(tts_h tts, int* count); + +/** +* @brief Gets the current state of tts. +* +* @param[in] tts The handle for TTS +* @param[out] state The current state of TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @see tts_play() +* @see tts_stop() +* @see tts_pause() +*/ +int tts_get_state(tts_h tts, tts_state_e* state); + +/** +* @brief Adds a text to the queue. +* +* @param[in] tts The handle for TTS +* @param[in] text A input text +* @param[in] language The language selected from the foreach function +* @param[in] voice_type The voice type selected from the foreach function +* @param[in] speed A speaking speed +* @param[out] utt_id The utterance ID passed to the callback function. +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_INVALID_VOICE Invalid voice about language, voice type +* @retval #TTS_ERROR_OUT_OF_MEMORY Out of memory +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @see tts_get_max_text_count() +*/ +int tts_add_text(tts_h tts, const char* text, const char* language, tts_voice_type_e voice_type, tts_speed_e speed, int* utt_id); + +/** +* @brief Starts synthesizing voice from text and plays synthesized audio data. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_INVALID_STATE Invalid state +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @pre The current state should be #TTS_STATE_READY or #TTS_STATE_PAUSED. +* @post If this function succeeds, the TTS state will be #TTS_STATE_PLAYING. +* +* @see tts_add_text() +* @see tts_pause() +* @see tts_stop() +* @see tts_utterance_started_cb() +* @see tts_utterance_completed_cb() +* @see tts_error_cb() +* @see tts_interrupted_cb() +*/ +int tts_play(tts_h tts); + +/** +* @brief Stops playing utterance and clears queue. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_INVALID_STATE Invalid state +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @pre The TTS state should be #TTS_STATE_PLAYING or #TTS_STATE_PAUSED. +* @post If this function succeeds, the TTS state will be #TTS_STATE_READY. +* This function will remove all text via tts_add_text() and synthesized sound data. +* +* @see tts_play() +* @see tts_pause() +*/ +int tts_stop(tts_h tts); + +/** +* @brief Pauses currently playing utterance. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTS_ERROR_INVALID_STATE Invalid state +* @retval #TTS_ERROR_OPERATION_FAILED Operation failure +* +* @pre The TTS state should be #TTS_STATE_PLAYING. +* @post If this function succeeds, the TTS state will be #TTS_STATE_PAUSED. +* +* @see tts_play() +* @see tts_stop() +* @see tts_error_cb() +* @see tts_interrupted_cb() +*/ +int tts_pause(tts_h tts); + +/** +* @brief Registers a callback function for detecting player interrupted. +* +* @param[in] tts The handle for TTS +* @param[in] callback The callback function to register +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_interrupted_cb() +* @see tts_unset_interrupted_cb() +*/ +int tts_set_interrupted_cb(tts_h tts, tts_interrupted_cb callback, void* user_data); + +/** +* @brief Unregisters the callback function. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_set_interrupted_cb() +*/ +int tts_unset_interrupted_cb(tts_h tts); + +/** +* @brief Registers a callback function for detecting utterance started. +* +* @param[in] tts The handle for TTS +* @param[in] callback The callback function to register +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_utterance_started_cb() +* @see tts_unset_utterance_started_cb() +*/ +int tts_set_utterance_started_cb(tts_h tts, tts_utterance_started_cb callback, void* user_data); + +/** +* @brief Unregisters the callback function. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_set_utterance_started_cb() +*/ +int tts_unset_utterance_started_cb(tts_h tts); + +/** +* @brief Registers a callback function for detecting utterance completed. +* +* @param[in] tts The handle for TTS +* @param[in] callback The callback function to register +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_utterance_completed_cb() +* @see tts_unset_utterance_completed_cb() +*/ +int tts_set_utterance_completed_cb(tts_h tts, tts_utterance_completed_cb callback, void* user_data); + +/** +* @brief Unregisters the callback function. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_OUT_OF_MEMORY Out of memory +* +* @see tts_set_utterance_completed_cb() +*/ +int tts_unset_utterance_completed_cb(tts_h tts); + +/** +* @brief Registers a callback function for detecting error. +* +* @param[in] tts The handle for TTS +* @param[in] callback The callback function to register +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_error_cb() +* @see tts_unset_error_cb() +*/ +int tts_set_error_cb(tts_h tts, tts_error_cb callback, void* user_data); + +/** +* @brief Unregisters the callback function. +* +* @param[in] tts The handle for TTS +* +* @return 0 on success, otherwise a negative error value +* @retval #TTS_ERROR_NONE Successful +* @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see tts_set_error_cb() +*/ +int tts_unset_error_cb(tts_h tts); + + +#ifdef __cplusplus +} +#endif + +/** +* @} +*/ + +#endif /* __TTS_H__ */ diff --git a/client/tts.pc.in b/client/tts.pc.in new file mode 100644 index 0000000..8ec8880 --- /dev/null +++ b/client/tts.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: lib@PROJECT_NAME@ +Description: Text To Speech client library +Requires: glib-2.0 dbus-1 +Version: @VERSION@ +Libs: -L${libdir} -l@PROJECT_NAME@ +Cflags: -I${includedir} diff --git a/client/tts_client.c b/client/tts_client.c new file mode 100644 index 0000000..450a30a --- /dev/null +++ b/client/tts_client.c @@ -0,0 +1,189 @@ +/* +* Copyright (c) 2011 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 "tts_client.h" + +/* Max number of handle */ +static const int g_max_handle = 999; +/* allocated handle */ +static int g_allocated_handle = 0; +/* client list */ +static GList *g_client_list = NULL; + +/* private functions */ +static int __client_generate_uid(int pid) +{ + g_allocated_handle++; + + if (g_allocated_handle > g_max_handle) { + g_allocated_handle = 1; + } + + /* generate uid, handle number should be smaller than 1000 */ + return pid * 1000 + g_allocated_handle; +} + +int tts_client_new(tts_h* tts) +{ + tts_client_s* client = NULL; + client = (tts_client_s*)g_malloc0 (sizeof(tts_client_s)); + + tts_h temp = (tts_h)g_malloc0(sizeof(tts_h)); + temp->handle = __client_generate_uid(getpid()); + + /* initialize client data */ + client->tts = temp; + client->pid = getpid(); + client->uid = temp->handle; + client->current_utt_id = 0; + + client->interrupted_cb = NULL; + client->interrupted_user_data = NULL; + + client->utt_started_cb = NULL; + client->utt_started_user_data = NULL; + client->utt_completeted_cb = NULL; + client->utt_completed_user_data = NULL; + + client->error_cb = NULL; + client->error_user_data = NULL; + + client->current_state = TTS_STATE_READY; + + client->cb_ref_count = 0; + + g_client_list = g_list_append(g_client_list, client); + + *tts = temp; + + SLOG(LOG_DEBUG, TAG_TTSC, "[Success] Create client object : uid(%d)", client->uid); + + return 0; +} + +int tts_client_destroy(tts_h tts) +{ + if (tts == NULL) { + SLOG(LOG_ERROR, TAG_TTSC, "Input parameter is NULL"); + return 0; + } + + GList *iter = NULL; + tts_client_s *data = NULL; + + /* if list have item */ + if (g_list_length(g_client_list) > 0) { + /* Get a first item */ + iter = g_list_first(g_client_list); + + while (NULL != iter) { + data = iter->data; + if (tts->handle == data->tts->handle) { + g_client_list = g_list_remove_link(g_client_list, iter); + + while (0 != data->cb_ref_count) + { + /* wait for release callback function */ + } + free(data); + free(tts); + + return 0; + } + + /* Next item */ + iter = g_list_next(iter); + } + } + SLOG(LOG_ERROR, TAG_TTSC, "Fail to destroy client : handle is not valid"); + + return -1; +} + +tts_client_s* tts_client_get(tts_h tts) +{ + if (tts == NULL) { + SLOG(LOG_ERROR, TAG_TTSC, "Input parameter is NULL"); + return NULL; + } + + GList *iter = NULL; + tts_client_s *data = NULL; + + if (g_list_length(g_client_list) > 0) { + /* Get a first item */ + iter = g_list_first(g_client_list); + + while (NULL != iter) { + data = iter->data; + + if (tts->handle == data->tts->handle) + return data; + + /* Next item */ + iter = g_list_next(iter); + } + } + + SLOG(LOG_ERROR, TAG_TTSC, "handle is not valid"); + + return NULL; +} + +tts_client_s* tts_client_get_by_uid(const int uid) +{ + if (uid < 0) { + SLOG(LOG_ERROR, TAG_TTSC, "out of range : handle"); + return NULL; + } + + GList *iter = NULL; + tts_client_s *data = NULL; + + if (g_list_length(g_client_list) > 0) { + /* Get a first item */ + iter = g_list_first(g_client_list); + + while (NULL != iter) { + data = iter->data; + if (uid == data->uid) { + return data; + } + + /* Next item */ + iter = g_list_next(iter); + } + } + + SLOG(LOG_WARN, TAG_TTSC, "uid is not valid"); + + return NULL; +} + +int tts_client_get_size() +{ + return g_list_length(g_client_list); +} + +int tts_client_use_callback(tts_client_s* client) +{ + client->cb_ref_count++; + return 0; +} + +int tts_client_not_use_callback(tts_client_s* client) +{ + client->cb_ref_count--; + return 0; +} diff --git a/client/tts_client.h b/client/tts_client.h new file mode 100644 index 0000000..ad0a60c --- /dev/null +++ b/client/tts_client.h @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2011 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 __TTS_CLIENT_H_ +#define __TTS_CLIENT_H_ + +#include +#include "tts.h" +#include "tts_main.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + /* base info */ + tts_h tts; + int pid; + int uid; /*<< unique id = pid + handle */ + int current_utt_id; + + /* callback info */ + tts_interrupted_cb interrupted_cb; + void* interrupted_user_data; + tts_utterance_started_cb utt_started_cb; + void* utt_started_user_data; + tts_utterance_completed_cb utt_completeted_cb; + void* utt_completed_user_data; + tts_error_cb error_cb; + void* error_user_data; + + /* state */ + tts_state_e current_state; + + /* semaphore */ + int cb_ref_count; +}tts_client_s; + +int tts_client_new(tts_h* tts); + +int tts_client_destroy(tts_h tts); + +tts_client_s* tts_client_get(tts_h tts); + +tts_client_s* tts_client_get_by_uid(const int uid); + +int tts_client_get_size(); + +int tts_client_use_callback(tts_client_s* client); + +int tts_client_not_use_callback(tts_client_s* client); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTS_CLIENT_H_ */ diff --git a/client/tts_dbus.c b/client/tts_dbus.c new file mode 100644 index 0000000..41a2cd2 --- /dev/null +++ b/client/tts_dbus.c @@ -0,0 +1,732 @@ +/* +* Copyright (c) 2011 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 "tts_main.h" +#include "tts_dbus.h" +#include "tts_defs.h" + + +static Ecore_Fd_Handler* g_fd_handler = NULL; + +static DBusConnection* g_conn = NULL; + + +extern int __tts_cb_error(int uid, tts_error_e reason, int utt_id); + +extern int __tts_cb_interrupt(int uid, tts_interrupted_code_e code); + +extern int __tts_cb_utt_started(int uid, int utt_id); + +extern int __tts_cb_utt_completed(int uid, int utt_id); + + +static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler) +{ + DBusConnection* conn = (DBusConnection*)data; + + if (NULL == conn) return ECORE_CALLBACK_RENEW; + + dbus_connection_read_write_dispatch(conn, 50); + + DBusMessage* msg = NULL; + msg = dbus_connection_pop_message(conn); + + /* loop again if we haven't read a message */ + if (NULL == msg) { + return ECORE_CALLBACK_RENEW; + } + + DBusError err; + dbus_error_init(&err); + + char if_name[64]; + snprintf(if_name, 64, "%s%d", TTS_CLIENT_SERVICE_INTERFACE, getpid()); + + /* check if the message is a signal from the correct interface and with the correct name */ + if (dbus_message_is_signal(msg, if_name, TTS_SIGNAL_UTTERANCE_STARTED)) { + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get utterance started"); + int uid, uttid; + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get Utterance started - Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< Get Utterance started signal : uid(%d), uttid(%d) \n", uid, uttid); + __tts_cb_utt_started(uid, uttid); + } + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + }/* TTS_SIGNAL_UTTERANCE_STARTED */ + + else if (dbus_message_is_signal(msg, if_name, TTS_SIGNAL_UTTERANCE_COMPLETED)) { + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get utterance completed"); + int uid, uttid; + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get Utterance completed - Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< Get Utterance completed signal : uid(%d), uttid(%d) \n", uid, uttid); + __tts_cb_utt_completed(uid, uttid); + } + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + }/* TTS_SIGNAL_UTTERANCE_COMPLETED */ + + else if (dbus_message_is_signal(msg, if_name, TTS_SIGNAL_INTERRUPT)) { + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get interrupt callback"); + int uid; + int code; + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INT32, &code, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get Stop signal - Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< Get Interrupt signal : uid(%d) , interrupt code(%d)\n", uid, code); + __tts_cb_interrupt(uid, (tts_interrupted_code_e)code); + } + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + } /* TTS_SIGNAL_INTERRUPT */ + + else if (dbus_message_is_signal(msg, if_name, TTS_SIGNAL_ERROR)) { + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get error callback"); + + int uid; + int uttid; + int reason; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_INT32, &reason, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get Error signal - Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< Get Error signal : uid(%d), error(%d), uttid(%d)\n", uid, reason, uttid); + __tts_cb_error(uid, reason, uttid); + } + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + }/* TTS_SIGNAL_ERROR */ + + /* free the message */ + dbus_message_unref(msg); + + return ECORE_CALLBACK_PASS_ON; +} + + +int tts_dbus_open_connection() +{ + if (NULL != g_conn) { + SLOG(LOG_WARN, TAG_TTSC, "already existed connection "); + return 0; + } + + DBusError err; + int ret; + + /* initialise the error value */ + dbus_error_init(&err); + + /* connect to the DBUS system bus, and check for errors */ + g_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Dbus Connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + + if (NULL == g_conn) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] fail to get dbus connection \n"); + return TTS_ERROR_OPERATION_FAILED; + } + + int pid = getpid(); + + char service_name[64]; + memset(service_name, 0, 64); + snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); + + SLOG(LOG_DEBUG, TAG_TTSC, "Service name is %s\n", service_name); + + /* register our name on the bus, and check for errors */ + ret = dbus_bus_request_name(g_conn, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Name Error (%s)\n", err.message); + dbus_error_free(&err); + } + + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to open connection : Service name has already been existed. \n"); + return TTS_ERROR_OPERATION_FAILED; + } + + char rule[128]; + snprintf(rule, 128, "type='signal',interface='%s%d'", TTS_CLIENT_SERVICE_INTERFACE, pid); + + /* add a rule for which messages we want to see */ + dbus_bus_add_match(g_conn, rule, &err); + dbus_connection_flush(g_conn); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Match Error (%s)\n", err.message); + return TTS_ERROR_OPERATION_FAILED; + } + + int fd = 0; + dbus_connection_get_unix_fd(g_conn, &fd); + + g_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)listener_event_callback, g_conn, NULL, NULL); + + if (NULL == g_fd_handler) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get fd handler from ecore \n"); + return TTS_ERROR_OPERATION_FAILED; + } + + return 0; +} + + +int tts_dbus_close_connection() +{ + DBusError err; + dbus_error_init(&err); + + int pid = getpid(); + + char service_name[64]; + memset(service_name, 0, 64); + snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); + + dbus_bus_release_name (g_conn, service_name, &err); + + g_conn = NULL; + + return 0; +} + + +int tts_dbus_request_initialize(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_INITIALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts initialize : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts initialize : uid(%d)", uid); + } + + int pid = getpid(); + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts initialize : result = %d \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts initialize : result = %d \n", result); + } + + dbus_message_unref(msg); + + return result; +} + + +int tts_dbus_request_finalize(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_FINALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts finalize : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts finalize : uid(%d)", uid); + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts finalize : result = %d \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts finalize : result = %d \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_dbus_request_get_support_voice(int uid, tts_h tts, tts_supported_voice_cb callback, void* user_data) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_GET_SUPPORT_VOICES); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts get supported voices : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts get supported voices : uid(%d)", uid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + DBusMessageIter args; + int result = TTS_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err ); + + if (NULL != result_msg) { + if (dbus_message_iter_init(result_msg, &args)) { + /* Get result */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &result); + dbus_message_iter_next(&args); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts get supported voices : result = %d \n", result); + + int size ; + char* temp_char; + int temp_int; + + /* Get voice size */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &size); + dbus_message_iter_next(&args); + } + + if (0 >= size) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts size of voice error : size = %d \n", size); + } else { + int i=0; + for (i=0 ; i>>> Request tts get default voice : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts get default voice : uid(%d)", uid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + char* temp_lang; + int voice_type; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &temp_lang, + DBUS_TYPE_INT32, &voice_type, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + *lang = strdup(temp_lang); + *vctype = (tts_voice_type_e)voice_type; + + if (NULL == *lang) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts get default voice : Out of memory \n"); + result = TTS_ERROR_OUT_OF_MEMORY; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts get default voice : result(%d), lang(%s), vctype(%d) \n", result, *lang, *vctype); + } + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts get default voice : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + + +int tts_dbus_request_add_text(int uid, const char* text, const char* lang, int vctype, int speed, int uttid) +{ + if (NULL == text || NULL == lang) { + SLOG(LOG_ERROR, TAG_TTSC, "Input parameter is NULL"); + return TTS_ERROR_INVALID_PARAMETER; + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_ADD_QUEUE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts add text : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts add text : uid(%d), text(%s), lang(%s), type(%d), speed(%d), id(%d)", + uid, text, lang, vctype, speed, uttid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_STRING, &lang, + DBUS_TYPE_INT32, &vctype, + DBUS_TYPE_INT32, &speed, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 5000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts add text : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts add text : result(%d) \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts add text : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_dbus_request_play(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_PLAY ); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts play : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts play : uid(%d)", uid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 5000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts play : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts play : result(%d) \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts play : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + + +int tts_dbus_request_stop(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_STOP); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts stop : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts stop : uid(%d)", uid); + } + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 5000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts stop : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts stop : result(%d) \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts stop : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_dbus_request_pause(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_METHOD_PAUSE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts pause : Fail to make message \n"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request tts pause : uid(%d)", uid); + } + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_ERROR_OPERATION_FAILED; + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 5000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts pause : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Result message is NULL "); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts pause : result(%d) \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< tts pause : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} diff --git a/client/tts_dbus.h b/client/tts_dbus.h new file mode 100644 index 0000000..c252fc2 --- /dev/null +++ b/client/tts_dbus.h @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2011 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 __TTS_DBUS_H_ +#define __TTS_DBUS_H_ + +#include "tts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int tts_dbus_open_connection(); + +int tts_dbus_close_connection(); + +int tts_dbus_request_initialize(int uid); + +int tts_dbus_request_finalize(int uid); + +int tts_dbus_request_get_support_voice(int uid, tts_h tts, tts_supported_voice_cb callback, void* user_data); + +int tts_dbus_request_get_default_voice(int uid , char** lang, tts_voice_type_e* vctype); + +int tts_dbus_request_add_text(int uid, const char* text, const char* lang, int vctype, int speed, int uttid); + +int tts_dbus_request_remove_all_text(int uid); + + +int tts_dbus_request_play(int uid) ; + +int tts_dbus_request_stop(int uid); + +int tts_dbus_request_pause(int uid); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTS_DBUS_H_ */ diff --git a/client/tts_main.h b/client/tts_main.h new file mode 100644 index 0000000..e2cd331 --- /dev/null +++ b/client/tts_main.h @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2011 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 __TTS_MAIN_H_ +#define __TTS_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tts_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG_TTSC "ttsc" + +/** +* @brief A structure of handle for identification +*/ +struct tts_s { + int handle; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TTS_MAIN_H_ */ diff --git a/client/tts_setting.c b/client/tts_setting.c new file mode 100644 index 0000000..e8ecf9e --- /dev/null +++ b/client/tts_setting.c @@ -0,0 +1,542 @@ +/* +* Copyright (c) 2011 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 "tts_main.h" +#include "tts_setting.h" +#include "tts_setting_dbus.h" + +static bool g_is_setting_initialized = false; + +static int __check_tts_daemon(); + + +/* API Implementation */ +int tts_setting_initialize() +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Initialize TTS Setting"); + + /* Check daemon */ + __check_tts_daemon(); + + if (true == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS Setting has already been initialized. \n"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if( 0 != tts_setting_dbus_open_connection() ) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to open connection\n "); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } + + /* do request */ + int i = 0; + int ret = 0; + while(1) { + ret = tts_setting_dbus_request_initialize(); + + if( TTS_SETTING_ERROR_ENGINE_NOT_FOUND == ret ) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine not found"); + break; + } else if(ret) { + sleep(1); + if (i == 10) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Connection Time out"); + ret = TTS_SETTING_ERROR_TIMED_OUT; + break; + } + i++; + } else { + /* success to connect tts-daemon */ + break; + } + } + + if (0 == ret) { + g_is_setting_initialized = true; + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Initialize"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + + +int tts_setting_finalize() +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Finalize TTS Setting"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + int ret = tts_setting_dbus_request_finalilze(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_SETTING_ERROR_OPERATION_FAILED; + } + + if (0 != tts_setting_dbus_close_connection()) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to close connection\n "); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Finalize"); + } + + g_is_setting_initialized = false; + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_SETTING_ERROR_NONE; +} + +int tts_setting_foreach_supported_engines(tts_setting_supported_engine_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported engines"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Callback is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_get_engine_list(callback, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach supported engines"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_get_engine(char** engine_id) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get current engine"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == engine_id) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine id is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_get_engine(engine_id); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Get current engine"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_set_engine(const char* engine_id) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Set current engine"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == engine_id) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine id is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_set_engine(engine_id); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set current engine"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_foreach_surppoted_voices(tts_setting_supported_voice_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported voices"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_get_voice_list(callback, user_data); + + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach supported voices"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_get_default_voice(char** language, tts_setting_voice_type_e* voice_type) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default voice"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == language || NULL == voice_type) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_get_default_voice(language, voice_type); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach supported voices"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_set_default_voice(const char* language, tts_setting_voice_type_e voice_type) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Set default voice"); + + if (false == g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == language) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + if (voice_type < TTS_SETTING_VOICE_TYPE_MALE && TTS_SETTING_VOICE_TYPE_USER3 < voice_type ) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid voice type"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_set_default_voice(language, voice_type); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set default voice"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return TTS_SETTING_ERROR_NONE; +} + + +int tts_setting_get_default_speed(tts_setting_speed_e* speed) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default speed"); + + if (!g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == speed) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int temp; + temp = 0; + + int ret = tts_setting_dbus_request_get_default_speed(&temp); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + /* Copy value */ + *speed = (tts_setting_speed_e)temp; + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Get default speed : %d ", (int)*speed); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + + +int tts_setting_set_default_speed(tts_setting_speed_e speed) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Set default speed"); + + if (!g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (speed < TTS_SETTING_SPEED_VERY_SLOW && TTS_SETTING_SPEED_VERY_FAST < speed ) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid speed"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_set_default_speed((int)speed); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set default speed"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_foreach_engine_settings(tts_setting_engine_setting_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach engine setting"); + + if (!g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_get_engine_setting(callback, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach engine setting"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + +int tts_setting_set_engine_setting(const char* key, const char* value) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "===== Set engine setting"); + + if (!g_is_setting_initialized) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_STATE; + } + + if(NULL == key || NULL == value) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + int ret = tts_setting_dbus_request_set_engine_setting(key, value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Foreach engine setting"); + } + + SLOG(LOG_DEBUG, TAG_TTSC, "====="); + SLOG(LOG_DEBUG, TAG_TTSC, " "); + + return ret; +} + + + +/* Functions for tts-daemon fork */ +static bool __tts_is_alive() +{ + FILE *fp = NULL; + char buff[256]; + char cmd[256]; + int i=0; + + memset(buff, 0, sizeof(char)); + memset(cmd, 0, sizeof(char)); + + if ((fp = popen("ps -eo \"cmd\"", "r")) == NULL) { + SLOG(LOG_DEBUG, TAG_TTSC, "[TTS ERROR] popen error "); + return FALSE; + } + + while (fgets(buff, 255, fp)) { + if (i == 0) { + i++; + continue; + } + + sscanf(buff, "%s", cmd); + + if( 0 == strncmp(cmd, "[tts-daemon]", strlen("[tts-daemon]")) || + 0 == strncmp(cmd, "tts-daemon", strlen("tts-daemon")) || + 0 == strncmp(cmd, "/usr/bin/tts-daemon", strlen("/usr/bin/tts-daemon")) + ) { + SLOG(LOG_DEBUG, TAG_TTSC, "tts-daemon is ALIVE !!"); + fclose(fp); + return TRUE; + } + + i++; + } + fclose(fp); + + return FALSE; +} + +static void __my_sig_child(int signo, siginfo_t *info, void *data) +{ + int status; + pid_t child_pid, child_pgid; + + child_pgid = getpgid(info->si_pid); + SLOG(LOG_DEBUG, TAG_TTSC, "Signal handler: dead pid = %d, pgid = %d", info->si_pid, child_pgid); + + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if(child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + } + + return; +} + +static int __check_tts_daemon() +{ + if( TRUE == __tts_is_alive() ) + return 0; + + /* fork-exec tts-daemom */ + SLOG(LOG_DEBUG, TAG_TTSC, "tts-daemon is NOT alive. start tts-daemon."); + + int pid, i; + struct sigaction act, dummy; + + act.sa_handler = NULL; + act.sa_sigaction = __my_sig_child; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; + + if (sigaction(SIGCHLD, &act, &dummy) < 0) { + SLOG(LOG_ERROR, TAG_TTSC, "Cannot make a signal handler"); + return -1; + } + + pid = fork(); + + switch(pid) { + case -1: + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create tts-daemon "); + break; + + case 0: + setsid(); + for( i = 0 ; i < _NSIG ; i++ ) + signal(i, SIG_DFL); + + execl("/usr/bin/tts-daemon", "/usr/bin/tts-daemon", NULL); + break; + + default: + sleep(1); + break; + } + + return 0; +} \ No newline at end of file diff --git a/client/tts_setting.h b/client/tts_setting.h new file mode 100644 index 0000000..a13f143 --- /dev/null +++ b/client/tts_setting.h @@ -0,0 +1,317 @@ +/* +* Copyright (c) 2011 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 __TTS_SETTING_H__ +#define __TTS_SETTING_H__ + +#include +#include + +/** +* @addtogroup TTS_SETTING_MODULE +* @{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief Enumerations of error codes. +*/ +typedef enum { + TTS_SETTING_ERROR_NONE = 0, /**< Success, No error */ + TTS_SETTING_ERROR_OUT_OF_MEMORY = -ENOMEM, /**< Out of Memory */ + TTS_SETTING_ERROR_IO_ERROR = -EIO, /**< I/O error */ + TTS_SETTING_ERROR_INVALID_PARAMETER = -EINVAL, /**< Invalid parameter */ + TTS_SETTING_ERROR_INVALID_STATE = -0x0100021, /**< Invalid state */ + TTS_SETTING_ERROR_INVALID_VOICE = -0x0100022, /**< Invalid voice */ + TTS_SETTING_ERROR_ENGINE_NOT_FOUND = -0x0100023, /**< No available TTS-engine */ + TTS_SETTING_ERROR_TIMED_OUT = -0x0100024, /**< No answer from TTS daemon */ + TTS_SETTING_ERROR_OPERATION_FAILED = -0x0100025, /**< TTS daemon failed */ +} tts_setting_error_e; + +/** +* @brief Enumerations of speaking speed. +*/ +typedef enum { + TTS_SETTING_SPEED_AUTO = 0, /**< Speed from settings */ + TTS_SETTING_SPEED_VERY_SLOW, /**< Very slow */ + TTS_SETTING_SPEED_SLOW, /**< Slow */ + TTS_SETTING_SPEED_NORMAL, /**< Normal */ + TTS_SETTING_SPEED_FAST, /**< Fast */ + TTS_SETTING_SPEED_VERY_FAST /**< Very fast */ +} tts_setting_speed_e; + +/** +* @brief Enumerations of voice type. +*/ +typedef enum { + TTS_SETTING_VOICE_TYPE_AUTO = 0, /**< Voice type from settings or auto selection based language*/ + TTS_SETTING_VOICE_TYPE_MALE, /**< Male */ + TTS_SETTING_VOICE_TYPE_FEMALE, /**< Female */ + TTS_SETTING_VOICE_TYPE_CHILD, /**< Child */ + TTS_SETTING_VOICE_TYPE_USER1, /**< Engine defined */ + TTS_SETTING_VOICE_TYPE_USER2, /**< Engine defined */ + TTS_SETTING_VOICE_TYPE_USER3 /**< Engine defined */ +} tts_setting_voice_type_e; + +/** +* @brief Called to get a engine information. +* +* @param[in] engine_id Engine id. +* @param[in] engine_name engine name. +* @param[in] setting_path gadget path of engine specific setting. +* @param[in] user_data User data passed from the tts_setting_foreach_supported_engines(). +* +* @return @c true to continue with the next iteration of the loop, \n @c false to break out of the loop. +* @pre tts_setting_foreach_supported_engines() will invoke this callback. +* +* @see tts_setting_foreach_supported_engines() +*/ +typedef bool(*tts_setting_supported_engine_cb)(const char* engine_id, const char* engine_name, const char* setting_path, void* user_data); + +/** +* @brief Called to get a voice. +* +* @param[in] engine_id Engine id. +* @param[in] language A language is specified as an ISO 3166 alpha-2 two letter country-code +* followed by ISO 639-1 for the two-letter language code. +* For example, "ko_KR" for Korean, "en_US" for American English.. +* @param[in] voice_type Voice type. +* @param[in] user_data User data passed from the tts_setting_foreach_surppoted_voices(). +* +* @return @c true to continue with the next iteration of the loop, \n @c false to break out of the loop. +* @pre tts_setting_foreach_surppoted_voices() will invoke this callback. +* +* @see tts_setting_foreach_surppoted_voices() +*/ +typedef bool(*tts_setting_supported_voice_cb)(const char* engine_id, const char* language, tts_setting_voice_type_e voice_type, void* user_data); + +/** +* @brief Called to get a engine setting. +* +* @param[in] engine_id Engine id. +* @param[in] key Key. +* @param[in] value Value. +* @param[in] user_data User data passed from the tts_setting_foreach_engine_settings(). +* +* @return @c true to continue with the next iteration of the loop, \n @c false to break out of the loop. +* @pre tts_setting_foreach_engine_settings() will invoke this callback. +* +* @see tts_setting_foreach_engine_settings() +*/ +typedef bool(*tts_setting_engine_setting_cb)(const char* engine_id, const char* key, const char* value, void* user_data); + + +/** +* @brief Initialize TTS setting and connect to tts-daemon. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_TIMED_OUT tts daemon is blocked or tts daemon do not exist. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS setting has Already been initialized. +* @retval #TTS_SETTING_ERROR_ENGINE_NOT_FOUND No available tts-engine. Engine should be installed. +* +* @see tts_setting_finalize() +*/ +int tts_setting_initialize(void); + +/** +* @brief finalize tts setting and disconnect to tts-daemon. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_initialize() +*/ +int tts_setting_finalize(void); + +/** +* @brief Retrieve supported engine informations using callback function. +* +* @param[in] callback callback function +* @param[in] user_data User data to be passed to the callback function. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @post This function invokes tts_setting_supported_engine_cb() repeatedly for getting engine information. +* +* @see tts_setting_supported_engine_cb() +*/ +int tts_setting_foreach_supported_engines(tts_setting_supported_engine_cb callback, void* user_data); + +/** +* @brief Get current engine id. +* +* @remark If the function is success, @a engine_id must be released with free() by you. +* +* @param[out] engine_id engine id. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_OUT_OF_MEMORY Out of memory. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_set_engine() +*/ +int tts_setting_get_engine(char** engine_id); + +/** +* @brief Set current engine id. +* +* @param[in] engine_id engine id. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_get_engine() +*/ +int tts_setting_set_engine(const char* engine_id); + +/** +* @brief Get supported voices of current engine. +* +* @param[in] callback callback function. +* @param[in] user_data User data to be passed to the callback function. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @post This function invokes tts_setting_supported_voice_cb() repeatedly for getting supported voices. +* +* @see tts_setting_supported_voice_cb() +*/ +int tts_setting_foreach_surppoted_voices(tts_setting_supported_voice_cb callback, void* user_data); + +/** +* @brief Get a default voice of current engine. +* +* @remark If the function is success, @a language must be released with free() by you. +* +* @param[out] language current language +* @param[out] voice_type current voice type +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_OUT_OF_MEMORY Out of memory. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_set_default_voice() +*/ +int tts_setting_get_default_voice(char** language, tts_setting_voice_type_e* voice_type); + +/** +* @brief Set a default voice of current engine. +* +* @param[in] language language +* @param[in] voice_type voice type. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_get_default_voice() +*/ +int tts_setting_set_default_voice(const char* language, tts_setting_voice_type_e voice_type); + +/** +* @brief Get default speed. +* +* @param[out] speed voice speed. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_set_default_speed() +*/ +int tts_setting_get_default_speed(tts_setting_speed_e* speed); + +/** +* @brief Set a default speed. +* +* @param[in] speed voice speed +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_get_default_speed() +*/ +int tts_setting_set_default_speed(tts_setting_speed_e speed); + +/** +* @brief Get setting information of current engine. +* +* @param[in] callback callback function +* @param[in] user_data User data to be passed to the callback function. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @post This function invokes tts_setting_engine_setting_cb() repeatedly for getting engine settings. +* +* @see tts_setting_engine_setting_cb() +*/ +int tts_setting_foreach_engine_settings(tts_setting_engine_setting_cb callback, void* user_data); + +/** +* @brief Set setting information. +* +* @param[in] key Key. +* @param[in] value Value. +* +* @return 0 on success, otherwise a negative error value. +* @retval #TTS_SETTING_ERROR_NONE Success. +* @retval #TTS_SETTING_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #TTS_SETTING_ERROR_INVALID_STATE TTS Not initialized. +* @retval #TTS_SETTING_ERROR_OPERATION_FAILED Operation failure. +* +* @see tts_setting_foreach_engine_settings() +*/ +int tts_setting_set_engine_setting(const char* key, const char* value); + +#ifdef __cplusplus +} +#endif + +/** +* @} +*/ + +#endif /* __TTS_SETTING_H__ */ diff --git a/client/tts_setting_dbus.c b/client/tts_setting_dbus.c new file mode 100644 index 0000000..b56c099 --- /dev/null +++ b/client/tts_setting_dbus.c @@ -0,0 +1,909 @@ +/* +* Copyright (c) 2011 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 "tts_setting.h" +#include "tts_main.h" +#include "tts_setting_dbus.h" + + +static DBusConnection* g_conn = NULL; + +int tts_setting_dbus_open_connection() +{ + if (NULL != g_conn) { + SLOG(LOG_WARN, TAG_TTSC, "Already existed connection"); + return 0; + } + + DBusError err; + int ret; + + /* initialise the error value */ + dbus_error_init(&err); + + /* connect to the DBUS system bus, and check for errors */ + g_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Dbus Connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + + if (NULL == g_conn) { + SLOG(LOG_ERROR, TAG_TTSC, "Fail to get dbus connection \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } + + int pid = getpid(); + + char service_name[64]; + memset(service_name, 0, 64); + snprintf(service_name, 64, "%s%d", TTS_SETTING_SERVICE_NAME, pid); + + SLOG(LOG_DEBUG, TAG_TTSC, "service name is %s\n", service_name); + + /* register our name on the bus, and check for errors */ + ret = dbus_bus_request_name(g_conn, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Name Error (%s)\n", err.message); + dbus_error_free(&err); + } + + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + printf("fail dbus_bus_request_name()\n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int tts_setting_dbus_close_connection() +{ + DBusError err; + dbus_error_init(&err); + + int pid = getpid(); + + char service_name[64]; + memset(service_name, 0, 64); + snprintf(service_name, 64, "%s%d", TTS_SETTING_SERVICE_NAME, pid); + + dbus_bus_release_name(g_conn, service_name, &err); + + g_conn = NULL; + + return 0; +} + + +int tts_setting_dbus_request_initialize() +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_INITIALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting initialize : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting initialize"); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting initialize : result = %d \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting initialize : result = %d \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_finalilze() +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_FINALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting finalize : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting finalize"); + } + + int pid = getpid(); + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = 0; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting finalize : result = %d \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting finalize : result = %d \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_get_engine_list(tts_setting_supported_engine_cb callback, void* user_data) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_GET_ENGINE_LIST); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting get engine list : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting get engine list"); + } + + int pid = getpid(); + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + DBusMessageIter args; + + if (dbus_message_iter_init(result_msg, &args)) { + /* Get result */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &result); + dbus_message_iter_next(&args); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting get engine list : result = %d \n", result); + + int size ; + char* temp_id; + char* temp_name; + char* temp_path; + + /* Get engine count */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &size); + dbus_message_iter_next(&args); + } + + int i=0; + for (i=0 ; i>>> Request setting get engine : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting get engine "); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + char* temp; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_STRING, &temp, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + *engine_id = strdup(temp); + + if (NULL == *engine_id) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting get engine : Out of memory \n"); + result = TTS_SETTING_ERROR_OUT_OF_MEMORY; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting get engine : result(%d), engine id(%s)\n", result, *engine_id); + } + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting get engine : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + + +int tts_setting_dbus_request_set_engine(const char* engine_id) +{ + if (NULL == engine_id) { + SLOG(LOG_ERROR, TAG_TTSC, "Input parameter is NULL"); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_SET_ENGINE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting set engine : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting set engine : engine id(%s)", engine_id); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &engine_id, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block ( g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting set engine : result(%d) \n", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting set engine : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_get_voice_list(tts_setting_supported_voice_cb callback, void* user_data) +{ + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "Input parameter is NULL"); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_GET_VOICE_LIST); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting get voice list : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting get voice list"); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + DBusMessageIter args; + + if (NULL != result_msg) { + if (dbus_message_iter_init(result_msg, &args)) { + /* Get result */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &result); + dbus_message_iter_next(&args); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting get voice list : result = %d \n", result); + + int size = 0; + char* temp_id = NULL; + char* temp_lang = NULL; + int temp_type; + + /* Get current voice */ + dbus_message_iter_get_basic(&args, &temp_id); + dbus_message_iter_next(&args); + + if (NULL != temp_id) { + /* Get voice count */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &size); + dbus_message_iter_next(&args); + } + + int i=0; + for (i=0 ; i>>> Request setting get default voice : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting get default voice"); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + char* temp_char; + int temp_int; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &temp_char, + DBUS_TYPE_INT32, &temp_int, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + } + + if (0 == result) { + *language = strdup(temp_char); + *voice_type = (tts_setting_voice_type_e)temp_int; + + if (NULL == *language) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting get default voice : Out of memory \n"); + result = TTS_SETTING_ERROR_OUT_OF_MEMORY; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting get default voice : result(%d), lang(%s), vctype(%d) \n", result, *language, *voice_type); + } + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting get default voice : result(%d) \n", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_set_default_voice(const char* language, const int voicetype ) +{ + if (NULL == language) { + SLOG(LOG_ERROR, TAG_TTSC, "Input Parameter is NULL"); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_SET_DEFAULT_VOICE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting set default voice : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting set default voice : language(%s), type(%d)", language, voicetype); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &language, + DBUS_TYPE_INT32, &voicetype, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting set default voice : result(%d)", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting set default voice : result(%d)", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_get_default_speed(int* speed) +{ + if (NULL == speed) { + SLOG(LOG_ERROR, TAG_TTSC, "Input Parameter is NULL"); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_GET_DEFAULT_SPEED); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting get default speed : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting get default speed "); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int temp_int; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT32, &temp_int, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + *speed = temp_int; + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting get default speed : result(%d), speed(%d)", result, speed); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting get default speed : result(%d)", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_set_default_speed(const int speed) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_SET_DEFAULT_SPEED); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting set default speed : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting set default speed : speed(%d)", speed); + } + + int pid = getpid(); + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &speed, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = TTS_SETTING_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting set default speed : result(%d)", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting set default speed : result(%d)", result); + } + + dbus_message_unref(msg); + + return result; +} + +int tts_setting_dbus_request_get_engine_setting(tts_setting_engine_setting_cb callback, void* user_data) +{ + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "Input Parameter is NULL"); + return TTS_SETTING_ERROR_INVALID_PARAMETER; + } + + DBusMessage* msg; + + msg = dbus_message_new_method_call( + TTS_SERVER_SERVICE_NAME, + TTS_SERVER_SERVICE_OBJECT_PATH, + TTS_SERVER_SERVICE_INTERFACE, + TTS_SETTING_METHOD_GET_ENGINE_SETTING); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request setting get engine setting : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting get engine setting"); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + DBusMessageIter args; + + if (dbus_message_iter_init(result_msg, &args)) { + /* Get result */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &result); + dbus_message_iter_next(&args); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< get engine setting : result = %d \n", result); + int size; + char* temp_id = NULL; + char* temp_key; + char* temp_value; + + /* Get engine id */ + dbus_message_iter_get_basic(&args, &temp_id); + dbus_message_iter_next(&args); + + if (NULL != temp_id) { + /* Get setting count */ + if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&args)) { + dbus_message_iter_get_basic(&args, &size); + dbus_message_iter_next(&args); + } + + int i=0; + for (i=0 ; i>>> Request setting set engine setting : Fail to make message \n"); + return TTS_SETTING_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSC, ">>>> Request setting set engine setting : key(%s), value(%s)", key, value); + } + + int pid = getpid(); + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &key, + DBUS_TYPE_STRING, &value, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = TTS_SETTING_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, 3000, &err); + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + result = -1; + } + dbus_message_unref(result_msg); + } + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_TTSC, "<<<< setting set engine setting : result(%d)", result); + } else { + SLOG(LOG_ERROR, TAG_TTSC, "<<<< setting set engine setting : result(%d)", result); + } + + dbus_message_unref(msg); + + return result; +} + diff --git a/client/tts_setting_dbus.h b/client/tts_setting_dbus.h new file mode 100644 index 0000000..5894afc --- /dev/null +++ b/client/tts_setting_dbus.h @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2011 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 __TTS_SETTING_DBUS_H_ +#define __TTS_SETTING_DBUS_H_ + +#include "tts_setting.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +int tts_setting_dbus_open_connection(); + +int tts_setting_dbus_close_connection(); + + +int tts_setting_dbus_request_initialize(); + +int tts_setting_dbus_request_finalilze(); + +int tts_setting_dbus_request_get_engine_list(tts_setting_supported_engine_cb callback, void* user_data); + +int tts_setting_dbus_request_get_engine(char** engine_id); + +int tts_setting_dbus_request_set_engine(const char* engine_id ); + +int tts_setting_dbus_request_get_voice_list(tts_setting_supported_voice_cb callback, void* user_data); + +int tts_setting_dbus_request_get_default_voice(char** language, tts_setting_voice_type_e* voice_type); + +int tts_setting_dbus_request_set_default_voice(const char* language, const int voicetype ); + +int tts_setting_dbus_request_get_default_speed(int* speed); + +int tts_setting_dbus_request_set_default_speed(int speed); + +int tts_setting_dbus_request_get_engine_setting(tts_setting_engine_setting_cb callback, void* user_data); + +int tts_setting_dbus_request_set_engine_setting(const char* key, const char* value); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTS_SETTING_DBUS_H_ */ diff --git a/common/tts_defs.h b/common/tts_defs.h new file mode 100644 index 0000000..520b6e5 --- /dev/null +++ b/common/tts_defs.h @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2011 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 _TTS_DEFS_H__ +#define _TTS_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************************** +* Definition for IPC +*******************************************************************************************/ + +#define TTS_CLIENT_SERVICE_NAME "com.samsung.voice.ttsclient" +#define TTS_CLIENT_SERVICE_OBJECT_PATH "/com/samsung/voice/ttsclient" +#define TTS_CLIENT_SERVICE_INTERFACE "com.samsung.voice.ttsclient" + +#define TTS_SETTING_SERVICE_NAME "com.samsung.voice.ttssetting" +#define TTS_SETTING_SERVICE_OBJECT_PATH "/com/samsung/voice/ttssetting" +#define TTS_SETTING_SERVICE_INTERFACE "com.samsung.voice.ttssetting" + +#define TTS_SERVER_SERVICE_NAME "service.connect.ttsserver" +#define TTS_SERVER_SERVICE_OBJECT_PATH "/com/samsung/voice/ttsserver" +#define TTS_SERVER_SERVICE_INTERFACE "com.samsung.voice.ttsserver" + + +/****************************************************************************************** +* Message Definition for APIs +*******************************************************************************************/ + +#define TTS_METHOD_INITIALIZE "tts_method_initialize" +#define TTS_METHOD_FINALIZE "tts_method_finalilze" +#define TTS_METHOD_GET_SUPPORT_VOICES "tts_method_get_support_voices" +#define TTS_METHOD_GET_CURRENT_VOICE "tts_method_get_current_voice" +#define TTS_METHOD_ADD_QUEUE "tts_method_add_queue" +#define TTS_METHOD_PLAY "tts_method_play" +#define TTS_METHOD_STOP "tts_method_stop" +#define TTS_METHOD_PAUSE "tts_method_pause" + +#define TTS_SIGNAL_INTERRUPT "tts_signal_interrupt" +#define TTS_SIGNAL_UTTERANCE_STARTED "tts_utterance_started" +#define TTS_SIGNAL_UTTERANCE_COMPLETED "tts_utterance_completed" +#define TTS_SIGNAL_ERROR "tts_signal_error" + + +/****************************************************************************************** +* Message Definition for Setting +*******************************************************************************************/ + +#define TTS_SETTING_METHOD_INITIALIZE "tts_setting_method_initialize" +#define TTS_SETTING_METHOD_FINALIZE "tts_setting_method_finalilze" +#define TTS_SETTING_METHOD_GET_ENGINE_LIST "tts_setting_method_get_engine_list" +#define TTS_SETTING_METHOD_GET_ENGINE "tts_setting_method_get_engine" +#define TTS_SETTING_METHOD_SET_ENGINE "tts_setting_method_set_engine" +#define TTS_SETTING_METHOD_GET_VOICE_LIST "tts_setting_method_get_voice_list" +#define TTS_SETTING_METHOD_GET_DEFAULT_VOICE "tts_setting_method_get_voice" +#define TTS_SETTING_METHOD_SET_DEFAULT_VOICE "tts_setting_method_set_voice" +#define TTS_SETTING_METHOD_GET_DEFAULT_SPEED "tts_setting_method_get_speed" +#define TTS_SETTING_METHOD_SET_DEFAULT_SPEED "tts_setting_method_set_speed" +#define TTS_SETTING_METHOD_GET_ENGINE_SETTING "tts_setting_method_get_engine_setting" +#define TTS_SETTING_METHOD_SET_ENGINE_SETTING "tts_setting_method_set_engine_setting" + +/****************************************************************************************** +* Message Definition for tts-daemon internal +*******************************************************************************************/ + +#define TTS_SIGNAL_NEXT_PLAY "tts_signal_start_play" +#define TTS_SIGNAL_NEXT_SYNTHESIS "tts_signal_start_synthesis" + +#ifdef __cplusplus +} +#endif + +#endif /* _TTS_DEFS_H__ */ diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..ce8316b --- /dev/null +++ b/debian/changelog @@ -0,0 +1,7 @@ +tts (0.1.1-1) unstable; urgency=low + + * beta release + * Git: tizen2/pkgs/t/tts + * Tag: tts_0.1.1-1 + + -- Dongyeol Lee Fri, 17 Feb 2012 14:48:00 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..875837c --- /dev/null +++ b/debian/control @@ -0,0 +1,25 @@ +Source: tts +Section: libs +Priority: standard +Maintainer: Dongyeol Lee +Build-Depends: debhelper (>= 5), libglib2.0-dev, libdbus-1-dev, + libmm-player-dev, libmm-common-dev, dlog-dev, libecore-dev +Standards-Version: 3.7.2 + +Package: libtts-dev +Section: libdevel +Architecture: any +Depends: libtts (= ${Source-Version}) +Description: Text To Speech header files for TTS development + +Package: libtts +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Text To Speech client library and daemon + +Package: libtts-dbg +Section: debug +Architecture: any +Depends: libtts (= ${Source-Version}) +Description: Text To Speech library (unstripped) diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..0592e06 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,12 @@ +Copyright (c) 2011 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. + + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..93e3f6a --- /dev/null +++ b/debian/docs @@ -0,0 +1,3 @@ +CMakeCache.txt +CMakeLists.txt + diff --git a/debian/libtts-dev.install.in b/debian/libtts-dev.install.in new file mode 100644 index 0000000..51c4ffb --- /dev/null +++ b/debian/libtts-dev.install.in @@ -0,0 +1,5 @@ +@PREFIX@/lib/pkgconfig/tts.pc +@PREFIX@/lib/pkgconfig/tts-setting.pc +@PREFIX@/include/tts.h +@PREFIX@/include/tts_setting.h +@PREFIX@/include/ttsp.h diff --git a/debian/libtts.install.in b/debian/libtts.install.in new file mode 100644 index 0000000..28666bf --- /dev/null +++ b/debian/libtts.install.in @@ -0,0 +1,2 @@ +@PREFIX@/lib/lib*.so* +@PREFIX@/bin/tts-daemon diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..e7d3c58 --- /dev/null +++ b/debian/rules @@ -0,0 +1,137 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS += -Wall -g +CXXFLAGS += -Wall -g +LDFLAGS += +PREFIX += /usr +DATADIR += /opt + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 + CXXFLAGS += -O0 +else + CFLAGS += -O2 + CXXFLAGS += -O2 +endif + +CFLASGS += -fpie +CXXFLAGS += -fpie +#LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed -pie +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -pie + +CFLASGS += -fpie +CXXFLAGS += -fpie +#LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed -pie +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -pie + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake . -DCMAKE_INSTALL_PREFIX=${PREFIX} + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + #docbook-to-man debian/client.sgml > client.1 + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + rm -rf CMakeCache.txt + rm -rf CMakeFiles + rm -rf cmake_install.cmake + rm -rf Makefile + rm -rf install_manifest.txt + rm -rf client/CMakeCache.txt + rm -rf client/CMakeFiles + rm -rf client/cmake_install.cmake + rm -rf client/Makefile + rm -rf client/install_manifest.txt + rm -rf client/*.pc + rm -rf server/CMakeCache.txt + rm -rf server/CMakeFiles + rm -rf server/cmake_install.cmake + rm -rf server/Makefile + rm -rf server/install_manifest.txt + rm -rf server/*.pc + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/client. + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=libtts-dbg + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/packaging/tts.spec b/packaging/tts.spec new file mode 100644 index 0000000..d3788e7 --- /dev/null +++ b/packaging/tts.spec @@ -0,0 +1,68 @@ +Name: tts +Summary: Text To Speech client library and daemon +Version: 0.1.1 +Release: 1 +Group: libs +License: Samsung +Source0: tts-0.1.1.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(mm-player) +BuildRequires: pkgconfig(mm-common) +BuildRequires: pkgconfig(dnet) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(ecore-input) +BuildRequires: pkgconfig(openssl) + +BuildRequires: cmake + +%description +Text To Speech client library and daemon. + + +%package devel +Summary: Text To Speech header files for TTS development +Group: libdevel +Requires: %{name} = %{version}-%{release} + +%description devel +Text To Speech header files for TTS development. + + +%prep +%setup -q -n %{name}-%{version} + + +%build +cmake . -DCMAKE_INSTALL_PREFIX=/usr +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + + + + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + + + +%files +%defattr(-,root,root,-) +%{_libdir}/lib*.so +%{_bindir}/tts-daemon + + +%files devel +%defattr(-,root,root,-) +%{_libdir}/pkgconfig/tts.pc +%{_libdir}/pkgconfig/tts-setting.pc +%{_includedir}/tts.h +%{_includedir}/tts_setting.h +%{_includedir}/ttsp.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000..0c4132f --- /dev/null +++ b/server/CMakeLists.txt @@ -0,0 +1,68 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(tts-daemon) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}") +SET(LIBDIR "${PREFIX}/lib") +SET(INCLUDEDIR "${PREFIX}/include") +SET(VERSION 0.0.1) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}") +SET(LIBDIR "${PREFIX}/lib/voice/tts/1.0/engine") +SET(INCLUDEDIR "${PREFIX}/include") +SET(VERSION 0.0.1) + +SET(SRCS + ttsd_data.cpp + ttsd_player.cpp + ttsd_engine_agent.c + ttsd_config.c + ttsd_server.cpp + ttsd_network.c + ttsd_dbus.c + ttsd_dbus_server.c + ttsd_main.c +) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${INCLUDEDIR}) +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/../common") + + +## Dependent packages ## +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + mm-player mm-common vconf dbus-1 + dlog openssl +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(CMAKE_EXE_LINKER_FLAGS "-Wall,--as-needed") + +## Add definitions ## +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"") +ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"") +ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +ADD_DEFINITIONS("-DLOCALEDIR=\"${LOCALEDIR}\"") +ADD_DEFINITIONS("-DEDJDIR=\"${EDJDIR}\"") +ADD_DEFINITIONS("-DIMAGEDIR=\"${IMAGEDIR}\"") + +## Executable ## +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) +#ADD_DEPENDENCIES(${PROJECT_NAME} ttsd_dbus_stub.h) + +## Install ## +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ttsp.h DESTINATION include) diff --git a/server/ttsd_config.c b/server/ttsd_config.c new file mode 100644 index 0000000..ee2a08b --- /dev/null +++ b/server/ttsd_config.c @@ -0,0 +1,222 @@ +/* +* Copyright (c) 2011 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 "ttsd_main.h" +#include "ttsd_config.h" + +/* +* tts-daemon config +*/ + +int ttsd_config_get_char_type(const char* key, char** value) +{ + if (NULL == key || NULL == value) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Input parameter is NULL\n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + *value = vconf_get_str(key); + if (NULL == *value) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to get char type from config : key(%s)\n", key); + return -1; + } + + return 0; +} + +int ttsd_config_set_char_type(const char* key, const char* value) +{ + if (NULL == key || NULL == value) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Input parameter is NULL\n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (0 != vconf_set_str(key, value)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to set char type \n"); + return -1; + } + + return 0; +} + +int ttsd_config_get_bool_type(const char* key, bool* value) +{ + if (NULL == key || NULL == value) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Input parameter is NULL\n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int result ; + if (0 != vconf_get_int(key, &result)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to get bool type config : key(%s)\n", key); + return -1; + } + + *value = (bool) result; + + return 0; +} + +int ttsd_config_set_bool_type(const char* key, const bool value) +{ + if (NULL == key) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Input parameter is NULL\n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int result = (int)value; + if (0 != vconf_set_int(key, result)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to set bool type config : key(%s)\n", key); + return -1; + } + + return 0; +} + +int ttsd_config_get_int_type(const char* key, int* value) +{ + if (NULL == key || NULL == value) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Input parameter is NULL\n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (0 != vconf_get_int(key, value)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to get bool type config : key(%s)\n", key); + return -1; + } + + return 0; +} + +int ttsd_config_set_int_type(const char* key, const int value) +{ + if (NULL == key) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Input parameter is NULL\n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (0 != vconf_set_int(key, value)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to set int type config : key(%s)\n", key); + return -1; + } + + return 0; +} + +/* +* interface for engine plug-in +*/ + +int config_make_key_for_engine(const char* engine_id, const char* key, char** out_key) +{ + int key_size = strlen(TTSD_CONFIG_PREFIX) + strlen(engine_id) + strlen(key) + 2; /* 2 is '/' and '\0' */ + + *out_key = (char*) g_malloc0( sizeof(char) * key_size); + + if (*out_key == NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] Not enough memory!! \n"); + return -1; + } else { + snprintf(*out_key, key_size, "%s%s/%s", TTSD_CONFIG_PREFIX, engine_id, key ); + SLOG(LOG_DEBUG, TAG_TTSD, "[Config DEBUG] make key (%s) \n", *out_key); + } + + return 0; +} + +int ttsd_config_set_persistent_data(const char* engine_id, const char* key, const char* value) +{ + char* vconf_key = NULL; + + if (0 != config_make_key_for_engine(engine_id, key, &vconf_key)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail config_make_key_for_engine()\n"); + return -1; + } + + if (0 != vconf_set_str(vconf_key, value)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to set key, value\n"); + + if(vconf_key != NULL) + g_free(vconf_key); + + return -1; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Config DEBUG] Set data : key(%s), value(%s) \n", vconf_key, value); + + if (vconf_key != NULL) + g_free(vconf_key); + + return 0; +} + +int ttsd_config_get_persistent_data(const char* engine_id, const char* key, char** value) +{ + char* vconf_key = NULL; + + if (0 != config_make_key_for_engine(engine_id, key, &vconf_key)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail config_make_key_for_engine()\n"); + return -1; + } + + char* temp; + temp = vconf_get_str(vconf_key); + if (temp == NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to get value\n"); + + if(vconf_key != NULL) + g_free(vconf_key); + + return -1; + } + + *value = g_strdup(temp); + + SLOG(LOG_DEBUG, TAG_TTSD, "[Config DEBUG] Get data : key(%s), value(%s) \n", vconf_key, *value); + + if (NULL != vconf_key) + g_free(vconf_key); + + if (NULL != temp) + g_free(temp); + + return 0; +} + +int ttsd_config_remove_persistent_data(const char* engine_id, const char* key) +{ + char* vconf_key = NULL; + int result = 0; + + if (0 != config_make_key_for_engine(engine_id, key, &vconf_key)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail config_make_key_for_engine()\n"); + return -1; + } + + if( NULL == vconf_key ) + return -1; + + if (0 != vconf_unset(vconf_key)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Config ERROR] fail to remove key\n"); + result = -1; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Config DEBUG] Remove data : key(%s)", vconf_key); + } + + if( vconf_key != NULL ) + g_free(vconf_key); + + return result; +} diff --git a/server/ttsd_config.h b/server/ttsd_config.h new file mode 100644 index 0000000..fca7d60 --- /dev/null +++ b/server/ttsd_config.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2011 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_CONFIG_H_ +#define __TTSD_CONFIG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TTSD_CONFIG_PREFIX "db/ttsd/" + +#define CONFIG_KEY_DEFAULT_ENGINE_ID TTSD_CONFIG_PREFIX"engine" +#define CONFIG_KEY_DEFAULT_LANGUAGE TTSD_CONFIG_PREFIX"language" +#define CONFIG_KEY_DEFAULT_VOICE_TYPE TTSD_CONFIG_PREFIX"vctype" +#define CONFIG_KEY_DEFAULT_SPEED TTSD_CONFIG_PREFIX"speed" + +/* +* tts-daemon config +*/ + +int ttsd_config_get_char_type(const char* key, char** value); + +int ttsd_config_set_char_type(const char* key, const char* value); + +int ttsd_config_get_bool_type(const char* key, bool* value); + +int ttsd_config_set_bool_type(const char* key, const bool value); + +int ttsd_config_get_int_type(const char* key, int* value); + +int ttsd_config_set_int_type(const char* key, const int value); + +/* +* interface for engine plug-in +*/ + +int ttsd_config_set_persistent_data(const char* engine_id, const char* key, const char* value); + +int ttsd_config_get_persistent_data(const char* engine_id, const char* key, char** value); + +int ttsd_config_remove_persistent_data(const char* engine_id, const char* key); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_CONFIG_H_ */ diff --git a/server/ttsd_data.cpp b/server/ttsd_data.cpp new file mode 100644 index 0000000..e2f7fb7 --- /dev/null +++ b/server/ttsd_data.cpp @@ -0,0 +1,433 @@ +/* +* Copyright (c) 2011 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 "ttsd_data.h" + +using namespace std; + +static vector g_app_list; + +static bool g_mutex_state = false; + +/* +* functions for debug +*/ + +int __data_show_list() +{ + int vsize = g_app_list.size(); + + SLOG(LOG_DEBUG, TAG_TTSD, "----- client list -----"); + + for (int i=0; ilang = g_strdup(g_app_list[index].m_speak_data[0].lang); + data->vctype = g_app_list[index].m_speak_data[0].vctype; + data->speed = g_app_list[index].m_speak_data[0].speed; + + data->text = g_app_list[index].m_speak_data[0].text; + data->utt_id = g_app_list[index].m_speak_data[0].utt_id; + + g_app_list[index].m_speak_data.erase(g_app_list[index].m_speak_data.begin()); + +#ifdef DATA_DEBUG + __data_show_text_list(index); +#endif + return TTSD_ERROR_NONE; +} + +int ttsd_data_add_sound_data(const int uid, const sound_data_s data) +{ + int index = 0; + index = ttsd_data_is_client(uid); + + if(index < 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[DATA ERROR] ttsd_data_add_sound_data() : uid is not valid (%d)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + g_app_list[index].m_wav_data.insert(g_app_list[index].m_wav_data.end(), data); + +#ifdef DATA_DEBUG + __data_show_sound_list(index); +#endif + return TTSD_ERROR_NONE; +} + +int ttsd_data_get_sound_data(const int uid, sound_data_s* data) +{ + int index = 0; + index = ttsd_data_is_client(uid); + + if (index < 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[DATA ERROR] ttsd_data_get_sound_data() : uid is not valid (%d)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (0 == g_app_list[index].m_wav_data.size()) { + SLOG(LOG_WARN, TAG_TTSD, "[DATA WARNING] There is no wav data\n"); + return -1; + } + + data->data = g_app_list[index].m_wav_data[0].data; + data->data_size = g_app_list[index].m_wav_data[0].data_size; + data->utt_id = g_app_list[index].m_wav_data[0].utt_id; + data->audio_type = g_app_list[index].m_wav_data[0].audio_type; + data->rate = g_app_list[index].m_wav_data[0].rate; + data->channels = g_app_list[index].m_wav_data[0].channels; + data->event = g_app_list[index].m_wav_data[0].event; + + g_app_list[index].m_wav_data.erase(g_app_list[index].m_wav_data.begin()); + +#ifdef DATA_DEBUG + __data_show_sound_list(index); +#endif + return TTSD_ERROR_NONE; +} + +int ttsd_data_get_sound_data_size(const int uid) +{ + int index = 0; + index = ttsd_data_is_client(uid); + + if (index < 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[DATA ERROR] ttsd_data_get_sound_data_size() : uid is not valid (%d)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + return g_app_list[index].m_wav_data.size(); +} + +int ttsd_data_clear_data(const int uid) +{ + int index = 0; + + index = ttsd_data_is_client(uid); + if (index < 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[DATA ERROR] ttsd_data_clear_data() : uid is not valid (%d)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int removed_last_uttid = -1; + /* free allocated data */ + while(1) { + speak_data_s temp; + if (0 != ttsd_data_get_speak_data(uid, &temp)) { + break; + } + + if (NULL != temp.text) free(temp.text); + if (NULL != temp.lang) free(temp.lang); + + removed_last_uttid = temp.utt_id; + } + + if (-1 != removed_last_uttid) { + g_app_list[index].utt_id_stopped = removed_last_uttid; + } + + while(1) { + sound_data_s temp; + if (0 != ttsd_data_get_sound_data(uid, &temp)) { + break; + } + + if (NULL != temp.data) free(temp.data); + } + + g_app_list[index].m_speak_data.clear(); + g_app_list[index].m_wav_data.clear(); + + return TTSD_ERROR_NONE; +} + +int ttsd_data_get_client_state(const int uid, app_state_e* state) +{ + int index = 0; + + index = ttsd_data_is_client(uid); + if (index < 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[DATA ERROR] ttsd_data_get_client_state() : uid is not valid (%d)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + *state = g_app_list[index].state; + + return TTSD_ERROR_NONE; +} + +int ttsd_data_set_client_state(const int uid, const app_state_e state) +{ + int index = 0; + + index = ttsd_data_is_client(uid); + if (index < 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[DATA ERROR] ttsd_data_set_client_state() : uid is not valid (%d)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (true == g_mutex_state) { + while(true == g_mutex_state) { + } + } + + g_mutex_state = true; + + /* The client of playing state of all clients is only one. need to check state. */ + if (APP_STATE_PLAYING == state) { + int vsize = g_app_list.size(); + for (int i=0 ; i +#include "ttsp.h" + +using namespace std; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + APP_STATE_READY = 0, + APP_STATE_PLAYING, + APP_STATE_PAUSED +}app_state_e; + +typedef struct +{ + int utt_id; + char* text; + char* lang; + ttsp_voice_type_e vctype; + ttsp_speed_e speed; +}speak_data_s; + +typedef struct +{ + int utt_id; + void* data; + unsigned int data_size; + + ttsp_result_event_e event; + ttsp_audio_type_e audio_type; + int rate; + int channels; +}sound_data_s; + +typedef struct +{ + int pid; + int uid; + int utt_id_stopped; + app_state_e state; + + std::vector m_speak_data; + std::vector m_wav_data; +}app_data_s; + + +int ttsd_data_new_client(const int pid, const int uid); + +int ttsd_data_delete_client(const int uid); + +int ttsd_data_is_client(const int uid); + +int ttsd_data_get_client_count(); + +int ttsd_data_get_pid(const int uid); + +int ttsd_data_add_speak_data(const int uid, const speak_data_s data); + +int ttsd_data_get_speak_data(const int uid, speak_data_s* data); + +int ttsd_data_get_speak_data_size(const int uid); + +int ttsd_data_add_sound_data(const int uid, const sound_data_s data); + +int ttsd_data_get_sound_data(const int uid, sound_data_s* data); + +int ttsd_data_get_sound_data_size(const int uid); + +int ttsd_data_clear_data(const int uid); + +int ttsd_data_get_client_state(const int pid, app_state_e* state); + +int ttsd_data_set_client_state(const int pid, const app_state_e state); + +int ttsd_data_get_current_playing(); + + +typedef bool(*ttsd_data_get_client_cb)(int pid, int uid, app_state_e state, void* user_data); + +int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data); + +bool ttsd_data_is_uttid_valid(int uid, int uttid); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_DATA_H_ */ diff --git a/server/ttsd_dbus.c b/server/ttsd_dbus.c new file mode 100644 index 0000000..20b5b28 --- /dev/null +++ b/server/ttsd_dbus.c @@ -0,0 +1,333 @@ +/* +* Copyright (c) 2011 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 + +#include "ttsd_main.h" +#include "ttsd_dbus_server.h" +#include "ttsd_dbus.h" +#include "ttsd_server.h" + + +static DBusConnection* g_conn; + +int ttsdc_send_signal(int pid, int uid, int uttid, char *signal) +{ + char target_if_name[64]; + snprintf(target_if_name, sizeof(target_if_name), "%s%d", TTS_CLIENT_SERVICE_INTERFACE, pid); + + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_signal( + TTS_CLIENT_SERVICE_OBJECT_PATH, /* object name of the signal */ + target_if_name, /* interface name of the signal */ + signal); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] Fail to create signal message : type(%s), uid(%d)\n", signal, uid); + return -1; + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INT32, &uttid, DBUS_TYPE_INVALID); + + /* send the message and flush the connection */ + if (!dbus_connection_send(g_conn, msg, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] <<<< send signal : Out Of Memory, type(%s), ifname(%s), uid(%d), uttid(%d) \n",signal, target_if_name, uid, uttid); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "<<<< send signal : type(%s), uid(%d), uttid(%d) \n", signal, uid, uttid); + + dbus_connection_flush(g_conn); + } + dbus_message_unref(msg); + + return 0; +} + +int ttsdc_send_utt_start_signal(int pid, int uid, int uttid) +{ + return ttsdc_send_signal(pid, uid, uttid, TTS_SIGNAL_UTTERANCE_STARTED); +} + +int ttsdc_send_utt_finish_signal(int pid, int uid, int uttid) +{ + return ttsdc_send_signal(pid, uid, uttid, TTS_SIGNAL_UTTERANCE_COMPLETED); +} + +int ttsdc_send_interrupt_signal(int pid, int uid, ttsd_interrupted_code_e code) +{ + return ttsdc_send_signal(pid, uid, (int)code, TTS_SIGNAL_INTERRUPT); +} + +int ttsdc_send_error_signal(int pid, int uid, int uttid, int reason) +{ + char target_if_name[128]; + snprintf(target_if_name, sizeof(target_if_name), "%s%d", TTS_CLIENT_SERVICE_INTERFACE, pid); + + DBusMessage* msg; + msg = dbus_message_new_signal( + TTS_CLIENT_SERVICE_OBJECT_PATH, /* object name of the signal */ + target_if_name, /* interface name of the signal */ + TTS_SIGNAL_ERROR ); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] Fail to create error message : uid(%d)\n", uid); + return -1; + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_INT32, &reason, + DBUS_TYPE_INVALID); + + if (!dbus_connection_send(g_conn, msg, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] <<<< Send error signal : Out Of Memory !\n"); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "<<<< Send error signal : reason(%d), uttid(%d)", reason, uttid); + dbus_connection_flush(g_conn); + } + + dbus_message_unref(msg); + + return 0; +} + +static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler) +{ + DBusConnection* conn = (DBusConnection*)data; + + if (NULL == conn) return ECORE_CALLBACK_RENEW; + + dbus_connection_read_write_dispatch(conn, 50); + + DBusMessage* msg = NULL; + msg = dbus_connection_pop_message(conn); + + /* loop again if we haven't read a message */ + if (NULL == msg) { + return ECORE_CALLBACK_RENEW; + } + + /* client event */ + if( dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_INITIALIZE) ) + ttsd_dbus_server_initialize(conn, msg); + + else if( dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_FINALIZE) ) + ttsd_dbus_server_finalize(conn, msg); + + else if( dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_GET_SUPPORT_VOICES) ) + ttsd_dbus_server_get_support_voices(conn, msg); + + else if( dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_GET_CURRENT_VOICE) ) + ttsd_dbus_server_get_current_voice(conn, msg); + + else if( dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_ADD_QUEUE) ) + ttsd_dbus_server_add_text(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_PLAY)) + ttsd_dbus_server_play(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_STOP)) + ttsd_dbus_server_stop(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_METHOD_PAUSE)) + ttsd_dbus_server_pause(conn, msg); + + /* setting event */ + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_INITIALIZE) ) + ttsd_dbus_server_setting_initialize(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_FINALIZE) ) + ttsd_dbus_server_setting_finalize(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_GET_ENGINE_LIST) ) + ttsd_dbus_server_setting_get_engine_list(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_GET_ENGINE) ) + ttsd_dbus_server_setting_get_engine(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_SET_ENGINE) ) + ttsd_dbus_server_setting_set_engine(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_GET_VOICE_LIST) ) + ttsd_dbus_server_setting_get_voice_list(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_GET_DEFAULT_VOICE) ) + ttsd_dbus_server_setting_get_default_voice(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_SET_DEFAULT_VOICE) ) + ttsd_dbus_server_setting_set_default_voice(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_GET_DEFAULT_SPEED) ) + ttsd_dbus_server_setting_get_speed(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_SET_DEFAULT_SPEED) ) + ttsd_dbus_server_setting_set_speed(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_GET_ENGINE_SETTING) ) + ttsd_dbus_server_setting_get_engine_setting(conn, msg); + + else if (dbus_message_is_method_call(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SETTING_METHOD_SET_ENGINE_SETTING) ) + ttsd_dbus_server_setting_set_engine_setting(conn, msg); + + /* daemon internal event*/ + else if (dbus_message_is_signal(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SIGNAL_NEXT_PLAY)) + ttsd_dbus_server_start_next_play(msg); + + else if (dbus_message_is_signal(msg, TTS_SERVER_SERVICE_INTERFACE, TTS_SIGNAL_NEXT_SYNTHESIS)) + ttsd_dbus_server_start_next_synthesis(msg); + + /* free the message */ + dbus_message_unref(msg); + + return ECORE_CALLBACK_RENEW; +} + +int ttsd_dbus_open_connection() +{ + DBusError err; + dbus_error_init(&err); + + int ret; + + /* connect to the bus and check for errors */ + g_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] fail dbus_bus_get : %s\n", err.message); + dbus_error_free(&err); + } + + if (NULL == g_conn) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] fail to get dbus connection \n" ); + return -1; + } + + /* request our name on the bus and check for errors */ + ret = dbus_bus_request_name(g_conn, TTS_SERVER_SERVICE_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + printf("Fail to be primary owner in dbus request. \n"); + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] fail to be primary owner \n"); + return -1; + } + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] dbus_bus_request_name() : %s \n", err.message); + dbus_error_free(&err); + + return -1; + } + + /* add a rule for getting signal */ + char rule[128]; + snprintf(rule, 128, "type='signal',interface='%s'", TTS_SERVER_SERVICE_INTERFACE); + + /* add a rule for which messages we want to see */ + dbus_bus_add_match(g_conn, rule, &err); /* see signals from the given interface */ + dbus_connection_flush(g_conn); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] dbus_bus_add_match() : %s \n", err.message); + return -1; + } + + int fd = 0; + dbus_connection_get_unix_fd(g_conn, &fd); + + Ecore_Fd_Handler* fd_handler; + fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ , (Ecore_Fd_Cb)listener_event_callback, g_conn, NULL, NULL); + + if (NULL == fd_handler) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] ecore_main_fd_handler_add() : fail to get fd handler \n"); + return -1; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Dbus SUCCESS] Open connection. "); + return 0; +} + +int ttsd_dbus_close_connection() +{ + DBusError err; + dbus_error_init(&err); + + dbus_bus_release_name (g_conn, TTS_SERVER_SERVICE_NAME, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] dbus_bus_release_name() : %s\n", err.message); + dbus_error_free(&err); + return -1; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Dbus SUCCESS] Close connection. "); + + return 0; +} + +int ttsd_send_start_next_play(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_signal( + TTS_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + TTS_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + TTS_SIGNAL_NEXT_PLAY ); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] >>>> Fail to make message for 'start next play'"); + return -1; + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + if (!dbus_connection_send(g_conn, msg, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] >>>> Fail to send message for 'start next play'\n"); + return -1; + } + + dbus_connection_flush(g_conn); + dbus_message_unref(msg); + + return 0; +} + +int ttsd_send_start_next_synthesis(int uid) +{ + DBusMessage* msg; + + msg = dbus_message_new_signal( + TTS_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + TTS_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + TTS_SIGNAL_NEXT_SYNTHESIS ); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] >>>> Fail to make message for 'start next synthesis'\n"); + return -1; + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + if (!dbus_connection_send(g_conn, msg, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Dbus ERROR] >>>> Fail to send message for 'start next synthesis'\n"); + return -1; + } + + dbus_connection_flush(g_conn); + dbus_message_unref(msg); + + return 0; +} diff --git a/server/ttsd_dbus.h b/server/ttsd_dbus.h new file mode 100644 index 0000000..18716cf --- /dev/null +++ b/server/ttsd_dbus.h @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2011 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_DBUS_h__ +#define __TTSD_DBUS_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +int ttsd_dbus_open_connection(); + +int ttsd_dbus_close_connection(); + + +int ttsdc_send_utt_start_signal(int pid, int uid, int uttid); + +int ttsdc_send_utt_finish_signal(int pid, int uid, int uttid); + +int ttsdc_send_error_signal(int pid, int uid, int uttid, int reason); + +int ttsdc_send_interrupt_signal(int pid, int uid, ttsd_interrupted_code_e code); + +int ttsd_send_start_next_play(int uid); + +int ttsd_send_start_next_synthesis(int uid); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_DBUS_h__ */ diff --git a/server/ttsd_dbus_server.c b/server/ttsd_dbus_server.c new file mode 100644 index 0000000..0cc9066 --- /dev/null +++ b/server/ttsd_dbus_server.c @@ -0,0 +1,1302 @@ +/* +* Copyright (c) 2011 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 "ttsd_dbus.h" +#include "ttsd_dbus_server.h" +#include "ttsd_server.h" + +extern int ttsd_data_get_pid(const int uid); + +/* +* Dbus Client-Daemon Server +*/ + +int ttsd_dbus_server_initialize(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid, uid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS INITIALIZE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts initialize : get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts initialize : pid(%d), uid(%d) \n", pid , uid); + ret = ttsd_server_initialize(pid, uid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts initialize : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts initialize : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts initialize : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts initialize : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_finalize(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + int ret = 0; + + dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS FINALIZE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts finalize : get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts finalize : uid(%d) \n", uid); + ret = ttsd_server_finalize(uid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts finalize : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts finalize : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts finalize : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts finalize : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_get_support_voices(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + int ret = 0; + GList* voice_list = NULL; + + dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS GET VOICES"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts get supported voices : get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] get supported voices : uid(%d) \n", uid ); + ret = ttsd_server_get_support_voices(uid, &voice_list); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + DBusMessageIter args; + dbus_message_iter_init_append(reply, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(ret)); + + if (0 == ret) { + /* Append voice size */ + int size = g_list_length(voice_list); + + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(size))) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts supported voices : Fail to append type \n"); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + + GList *iter = NULL; + voice_s* voice; + + iter = g_list_first(voice_list); + + while (NULL != iter) { + voice = iter->data; + + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(voice->language) ); + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(voice->type) ); + + if (NULL != voice->language) + g_free(voice->language); + if (NULL != voice); + g_free(voice); + + voice_list = g_list_remove_link(voice_list, iter); + + iter = g_list_first(voice_list); + } + } + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts supported voices : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts supported voices : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] error : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts supported voices : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_get_current_voice(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + char* lang; + int voice_type; + int ret; + + dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS GET DEFAULT VOICE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts get default voice : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts get default voice : uid(%d) \n", uid); + ret = ttsd_server_get_current_voice(uid, &lang, &voice_type); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (0 == ret) { + /* Append result and voice */ + dbus_message_append_args( reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_STRING, &lang, + DBUS_TYPE_INT32, &voice_type, + DBUS_TYPE_INVALID); + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts default voice : lang(%s), vctype(%d)\n", lang, voice_type ); + } else { + dbus_message_append_args( reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts default voice : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts default voice : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts default voice : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_add_text(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid, voicetype, speed, uttid; + char *text, *lang; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_STRING, &lang, + DBUS_TYPE_INT32, &voicetype, + DBUS_TYPE_INT32, &speed, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS ADD TEXT"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts add text : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts add text : uid(%d), text(%s), lang(%s), type(%d), speed(%d), uttid(%d) \n", + uid, text, lang, voicetype, speed, uttid); + ret = ttsd_server_add_queue(uid, text, lang, voicetype, speed, uttid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts add text : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts add text : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts add text : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts add text : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_play(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + int ret = 0; + + dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS PLAY"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts play : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts play : uid(%d) \n", uid ); + ret = ttsd_server_play(uid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts play : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts play : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts play : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts play : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_stop(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + int ret = 0; + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS STOP"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts stop : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts stop : uid(%d)\n", uid); + ret = ttsd_server_stop(uid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts stop : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts stop : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts stop : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts stop : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_pause(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + int uttid; + int ret = 0; + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTS PAUSE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] tts pause : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] tts pause : uid(%d)\n", uid); + ret = ttsd_server_pause(uid, &uttid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] tts pause : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts pause : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts pause : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] tts pause : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + + +/* +* Dbus Setting-Daemon Server +*/ + +int ttsd_dbus_server_setting_initialize(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING INITIALIZE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] Receivce setting initialize : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] Receivce setting initialize : pid(%d) \n", pid); + ret = ttsd_server_setting_initialize(pid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting initialize : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting initialize : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting initialize : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting initialize : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_finalize(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING FINALIZE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting finalize : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting finalize : pid(%d)\n", pid); + ret = ttsd_server_setting_finalize(pid); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting finalize : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting finalize : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting finalize : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting finalize : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_get_engine_list(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + GList* engine_list = NULL; + + dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET ENGINE LIST"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting engine list : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting engine list : pid(%d) \n", pid); + ret = ttsd_server_setting_get_engine_list(pid, &engine_list); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + DBusMessageIter args; + dbus_message_iter_init_append(reply, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(ret) ); + + if (0 == ret) { + /* Append size */ + int size = g_list_length(engine_list); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(size))) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting engine list : fail to append engine size \n"); + } else { + + GList *iter = NULL; + engine_s* engine; + + iter = g_list_first(engine_list); + + while (NULL != iter) { + engine = iter->data; + SLOG(LOG_DEBUG, TAG_TTSD, "engine id : %s, engine name : %s, ug_name, : %s", + engine->engine_id, engine->engine_name, engine->ug_name); + + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(engine->engine_id) ); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(engine->engine_name) ); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(engine->ug_name) ); + + if (NULL != engine->engine_id) + g_free(engine->engine_id); + if (NULL != engine->engine_name); + g_free(engine->engine_name); + if (NULL != engine->ug_name); + g_free(engine->ug_name); + if (NULL != engine); + g_free(engine); + + engine_list = g_list_remove_link(engine_list, iter); + + iter = g_list_first(engine_list); + } + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting engine list : result(%d) \n", ret); + } + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting engine list : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting engine list : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting engine list : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_get_engine(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + char* engine_id = NULL; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET ENGINE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting get engine : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting get engine : pid(%d)\n", pid); + ret = ttsd_server_setting_get_current_engine(pid, &engine_id); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (0 == ret) { + dbus_message_append_args( reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_STRING, &engine_id, DBUS_TYPE_INVALID); + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting get engine : result(%d), engine id(%s)\n", ret, engine_id); + } else { + dbus_message_append_args( reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get engine : result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get engine : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get engine : fail to create reply message!!"); + } + + if (NULL != engine_id) + free(engine_id); + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_set_engine(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + char* engine_id; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &engine_id, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING SET ENGINE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting set engine : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting set engine : pid(%d), engine id(%s)\n", pid, engine_id); + ret = ttsd_server_setting_set_current_engine(pid, engine_id); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting set engine : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set engine : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set engine : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set engine : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_get_voice_list(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + char* engine_id = NULL; + int ret = 0; + GList* voice_list = NULL; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET VOICE LIST"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting voice list : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting voice list : pid(%d)\n", pid); + ret = ttsd_server_setting_get_voice_list(pid, &engine_id, &voice_list); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + DBusMessageIter args; + + dbus_message_iter_init_append(reply, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(ret) ); + + if (0 == ret) { + if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(engine_id))) { + /* Append voice size */ + int size = g_list_length(voice_list); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(size))) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : Fail to append type \n"); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + + GList *iter = NULL; + voice_s* voice; + + iter = g_list_first(voice_list); + + while (NULL != iter) { + voice = iter->data; + + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(voice->language) ); + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(voice->type) ); + + if (NULL != voice->language) + g_free(voice->language); + if (NULL != voice); + g_free(voice); + + voice_list = g_list_remove_link(voice_list, iter); + + iter = g_list_first(voice_list); + } + } + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting voice list : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : Fail to append engine_id \n"); + } + + if (NULL != engine_id) + free(engine_id); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_get_default_voice(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + char* lang; + ttsp_voice_type_e type; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET DEFAULT VOICE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting get default voice : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting get default voice : pid(%d)\n", pid); + ret = ttsd_server_setting_get_default_voice(pid, &lang, &type); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (0 == ret) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_STRING, &lang, + DBUS_TYPE_INT32, &type, + DBUS_TYPE_INVALID); + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting get default voice : result(%d), language(%s), type(%d) \n", ret, lang, type); + } else { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get default voice : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get default voice : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get default voice : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_set_default_voice(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + char* language; + int voicetype; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &language, + DBUS_TYPE_INT32, &voicetype, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SET DEFAULT VOICE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting set default voice : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting set default voice : pid(%d), lang(%s), type(%d)\n" + , pid, language, voicetype); + ret = ttsd_server_setting_set_default_voice(pid, language, voicetype); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting set default voice : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set default voice : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set default voice : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set default voice : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_get_speed(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + int speed; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET SPEED"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting get speed : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting get default speed : pid(%d)\n", pid); + ret = ttsd_server_setting_get_default_speed(pid, &speed); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (0 == ret) { + dbus_message_append_args( reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INT32, &speed, DBUS_TYPE_INVALID); + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting get default speed : result(%d), speed(%d) \n", ret, speed); + } else { + dbus_message_append_args( reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get default speed : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get default speed : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get default speed : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_set_speed(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int speed; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &speed, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET SPEED"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting set default speed : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting set default speed : pid(%d), speed(%d)\n", pid, speed); + ret = ttsd_server_setting_set_default_speed(pid, speed); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting set default speed : result(%d)", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set default speed : result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set default speed : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set default speed : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_get_engine_setting(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + int ret = 0; + char* engine_id; + GList* engine_setting_list = NULL; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING GET ENGINE SETTING"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting get engine option : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting get engine option : pid(%d)", pid); + ret = ttsd_server_setting_get_engine_setting(pid, &engine_id, &engine_setting_list); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + DBusMessageIter args; + dbus_message_iter_init_append(reply, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(ret) ); + + if (0 == ret) { + if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(engine_id))) { + /* Append voice size */ + int size = g_list_length(engine_setting_list); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(size))) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : Fail to append type \n"); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + + GList *iter = NULL; + engine_setting_s* setting; + + iter = g_list_first(engine_setting_list); + + while (NULL != iter) { + setting = iter->data; + + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(setting->key) ); + dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(setting->value) ); + + if (NULL != setting->key) + g_free(setting->key); + if (NULL != setting->value) + g_free(setting->value); + if (NULL != setting); + g_free(setting); + + engine_setting_list = g_list_remove_link(engine_setting_list, iter); + + iter = g_list_first(engine_setting_list); + } + } + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting engine setting list : result(%d) \n", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting voice list : Fail to append engine_id \n"); + } + + if (NULL != engine_id) + free(engine_id); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get engine option : result(%d) \n", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get engine option : Out Of Memory!\n"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting get engine option : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_setting_set_engine_setting(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int pid; + char* key; + char* value; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &key, + DBUS_TYPE_STRING, &value, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> SETTING SET ENGINE SETTING"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] setting set engine option : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] setting set engine option : pid(%d), key(%s), value(%s)\n", pid, key, value); + ret = ttsd_server_setting_set_engine_setting(pid, key, value); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args( reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] setting set engine option : result(%d)", ret); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set engine option : result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set engine option : Out Of Memory!\n"); + } + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[OUT ERROR] setting set engine option : fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + + +/* +* Dbus Server functions for tts daemon intenal +*/ + +int ttsd_dbus_server_start_next_play(DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTSD NEXT PLAY"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] ttsd 'start next play' : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] ttsd 'start next play' : uid(%d) \n", uid); + int ret = ttsd_server_start_next_play(uid); + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] ttsd 'start next play' : result(%d) \n", ret); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +int ttsd_dbus_server_start_next_synthesis(DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + int uid; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &uid, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, TAG_TTSD, ">>>>> TTSD NEXT SYNTHESIS"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_TTSD, "[IN ERROR] ttsd 'start next synthesis' : Get arguments error (%s)\n", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[IN] ttsd 'start next synthesis' : uid(%d) \n", uid); + int ret = ttsd_server_start_next_synthesis(uid); + SLOG(LOG_DEBUG, TAG_TTSD, "[OUT] ttsd 'start next synthesis' : result(%d) \n", ret); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "<<<<<"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} \ No newline at end of file diff --git a/server/ttsd_dbus_server.h b/server/ttsd_dbus_server.h new file mode 100644 index 0000000..76a7410 --- /dev/null +++ b/server/ttsd_dbus_server.h @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2011 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_DBUS_SERVER_h__ +#define __TTSD_DBUS_SERVER_h__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* Dbus Server functions for APIs +*/ + +int ttsd_dbus_server_initialize(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_finalize(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_get_support_voices(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_get_current_voice(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_add_text(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_play(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_stop(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_pause(DBusConnection* conn, DBusMessage* msg); + + +/* +* Dbus Server functions for Setting +*/ + +int ttsd_dbus_server_setting_initialize(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_finalize(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_get_engine_list(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_get_engine(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_set_engine(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_get_voice_list(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_get_default_voice(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_set_default_voice(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_get_speed(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_set_speed(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_get_engine_setting(DBusConnection* conn, DBusMessage* msg); + +int ttsd_dbus_server_setting_set_engine_setting(DBusConnection* conn, DBusMessage* msg); + + +/* +* Dbus Server functions for tts daemon internal +*/ + +int ttsd_dbus_server_start_next_play(DBusMessage* msg); + +int ttsd_dbus_server_start_next_synthesis(DBusMessage* msg); + +#ifdef __cplusplus +} +#endif + + +#endif /* __TTSD_DBUS_SERVER_h__ */ diff --git a/server/ttsd_engine_agent.c b/server/ttsd_engine_agent.c new file mode 100644 index 0000000..08ac5c8 --- /dev/null +++ b/server/ttsd_engine_agent.c @@ -0,0 +1,1538 @@ +/* +* Copyright (c) 2011 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 + +#include "ttsd_main.h" +#include "ttsd_engine_agent.h" +#include "ttsd_config.h" + +#define ENGINE_PATH_SIZE 256 + +/* +* Internal data structure +*/ +typedef struct { + /* base info */ + char* engine_uuid; + char* engine_name; + char* engine_path; + + /* info for using engine load*/ + bool is_set; + bool is_loaded; + bool need_network; + void *handle; + + /* engine base setting */ + char* default_lang; + int default_vctype; + int default_speed; + + ttspe_funcs_s* pefuncs; + ttspd_funcs_s* pdfuncs; + + int (*ttsp_load_engine)(const ttspd_funcs_s* pdfuncs, ttspe_funcs_s* pefuncs); + int (*ttsp_unload_engine)(); +} ttsengine_s; + +typedef struct { + char* engine_uuid; + char* engine_path; + char* engine_name; + char* setting_ug_path; + bool use_network; +} ttsengine_info_s; + + +/** Init flag */ +static bool g_agent_init; + +/** TTS engine list */ +static GList *g_engine_list; + +/** Current engine information */ +static ttsengine_s g_cur_engine; + +/** Result callback function */ +static synth_result_callback g_result_cb; + + +/** Set current engine */ +int __internal_set_current_engine(const char* engine_uuid); + +/** Check engine id */ +int __internal_check_engine_id(const char* engine_uuid); + +/** Update engine list */ +int __internal_update_engine_list(); + +/** Get engine info */ +int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info); + +/** Callback function for result */ +bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, void *user_data); + +/** Callback function for voice list */ +bool __supported_voice_cb(const char* language, ttsp_voice_type_e type, void* user_data); + +/** Free voice list */ +void __free_voice_list(GList* voice_list); + +/** Callback function for engine info */ +void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, + bool use_network, void* user_data); + +/** Callback fucntion for engine setting */ +bool __engine_setting_cb(const char* key, const char* value, void* user_data); + + +int ttsd_engine_agent_init(synth_result_callback result_cb) +{ + /* initialize static data */ + if (result_cb == NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] invalid parameter \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + g_result_cb = result_cb; + + g_cur_engine.engine_uuid = NULL; + g_cur_engine.engine_name = NULL; + g_cur_engine.engine_path = NULL; + + g_cur_engine.is_set = false; + g_cur_engine.handle = NULL; + g_cur_engine.pefuncs = (ttspe_funcs_s*)g_malloc0( sizeof(ttspe_funcs_s) ); + g_cur_engine.pdfuncs = (ttspd_funcs_s*)g_malloc0( sizeof(ttspd_funcs_s) ); + + g_agent_init = true; + + if (0 != ttsd_config_get_char_type(CONFIG_KEY_DEFAULT_LANGUAGE, &(g_cur_engine.default_lang)) && + 0 != ttsd_config_get_int_type(CONFIG_KEY_DEFAULT_VOICE_TYPE, &(g_cur_engine.default_vctype)) ) { + /* Set default voice */ + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] There is No default voice in config\n"); + g_cur_engine.default_lang = strdup("en_US"); + g_cur_engine.default_vctype = TTSP_VOICE_TYPE_FEMALE; + } + + if (0 != ttsd_config_get_int_type(CONFIG_KEY_DEFAULT_SPEED, &(g_cur_engine.default_speed))) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] There is No default speed in config\n"); + ttsd_config_set_int_type(CONFIG_KEY_DEFAULT_SPEED, TTSP_SPEED_NORMAL); + g_cur_engine.default_speed = TTSP_SPEED_NORMAL; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] Initialize Engine Agent "); + + return 0; +} + +int ttsd_engine_agent_release() +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* unload current engine */ + ttsd_engine_agent_unload_current_engine(); + + /* release engine list */ + GList *iter = NULL; + ttsengine_s *data = NULL; + + if (g_list_length(g_engine_list) > 0) { + /* Get a first item */ + iter = g_list_first(g_engine_list); + + while (NULL != iter) { + /* Get data from item */ + data = iter->data; + dlclose(data->handle); + + iter = g_list_remove(iter, data); + } + } + + g_list_free(iter); + + /* release current engine data */ + if( g_cur_engine.pefuncs != NULL) + g_free(g_cur_engine.pefuncs); + + if( g_cur_engine.pdfuncs != NULL) + g_free(g_cur_engine.pdfuncs); + + g_result_cb = NULL; + g_agent_init = false; + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] Release Engine Agent\n"); + + return 0; +} + +int ttsd_engine_agent_initialize_current_engine() +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* update engine list */ + if (0 != __internal_update_engine_list()) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent WARNING] No engine error \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* 2. get current engine from config */ + char* cur_engine_uuid = NULL; + bool is_get_engineid_from_config = false; + + if (0 != ttsd_config_get_char_type(CONFIG_KEY_DEFAULT_ENGINE_ID ,&cur_engine_uuid)) { + /*not set current engine */ + /*set system default engine*/ + GList *iter = NULL; + ttsengine_info_s *data = NULL; + + if (g_list_length(g_engine_list) > 0) { + iter = g_list_first(g_engine_list); + char* default_engine = "27F277E9-BBC4-4dca-B553-D9884A3CDAA0"; + + while (NULL != iter) { + data = iter->data; + + if (0 == strncmp(data->engine_uuid, default_engine, strlen(default_engine))) { + /* current data is default engine */ + break; + } + + iter = g_list_next(iter); + } + } else { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent WARNING] Fail to set a engine of engine list\n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL != data->engine_uuid) { + cur_engine_uuid = strdup(data->engine_uuid); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Data of current engine is corrupt\n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + is_get_engineid_from_config = false; + } else { + is_get_engineid_from_config = true; + } + + /* check whether cur engine uuid is valid or not. */ + if (0 != __internal_check_engine_id(cur_engine_uuid)) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent WARNING] It is not valid engine id from config \n"); + + GList *iter = NULL; + + if (g_list_length(g_engine_list) > 0) + iter = g_list_first(g_engine_list); + else { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent ERROR] NO TTS Engine !! \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (cur_engine_uuid != NULL) + g_free(cur_engine_uuid); + + ttsengine_info_s *data = NULL; + data = iter->data; + + cur_engine_uuid = g_strdup(data->engine_uuid); + + is_get_engineid_from_config = false; + } + + if (NULL != cur_engine_uuid) + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] Current Engine Id : %s \n", cur_engine_uuid); + else + return TTSD_ERROR_OPERATION_FAILED; + + /* set current engine */ + if (0 != __internal_set_current_engine(cur_engine_uuid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to set current engine "); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == is_get_engineid_from_config) { + if (0 != ttsd_config_set_char_type(CONFIG_KEY_DEFAULT_ENGINE_ID ,cur_engine_uuid)) + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to set id to config \n"); + } + + if (NULL != cur_engine_uuid) + g_free(cur_engine_uuid); + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] Set current engine"); + + return 0; +} + +int __internal_check_engine_id(const char* engine_uuid) +{ + GList *iter = NULL; + ttsengine_s *data = NULL; + + if (g_list_length(g_engine_list) > 0) { + iter = g_list_first(g_engine_list); + + while (NULL != iter) { + data = iter->data; + + if (0 == strncmp(engine_uuid, data->engine_uuid, strlen(data->engine_uuid))) + return 0; + + iter = g_list_next(iter); + } + } + + return -1; +} + +void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, + bool use_network, void* user_data) +{ + ttsengine_info_s* temp = (ttsengine_info_s*)user_data; + + temp->engine_uuid = g_strdup(engine_uuid); + temp->engine_name = g_strdup(engine_name); + temp->setting_ug_path = g_strdup(setting_ug_name); + temp->use_network = use_network; +} + +int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info) +{ + char *error; + void* handle; + + handle = dlopen (filepath, RTLD_LAZY ); + + if (!handle) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent] Invalid engine : %s", filepath); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* link engine to daemon */ + dlsym(handle, "ttsp_load_engine"); + if ((error = dlerror()) != NULL) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent] Invalid engine. Fail to open ttsp_load_engine : %s", filepath); + dlclose(handle); + return TTSD_ERROR_OPERATION_FAILED; + } + + dlsym(handle, "ttsp_unload_engine"); + if ((error = dlerror()) != NULL) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent] Invalid engine. Fail to open ttsp_unload_engine : %s", filepath); + dlclose(handle); + return TTSD_ERROR_OPERATION_FAILED; + } + + int (*get_engine_info)(ttsp_engine_info_cb callback, void* user_data); + + get_engine_info = (int (*)(ttsp_engine_info_cb, void*))dlsym(handle, "ttsp_get_engine_info"); + if ((error = dlerror()) != NULL) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent] ttsp_get_engine_info() link error\n"); + dlclose(handle); + return TTSD_ERROR_OPERATION_FAILED; + } + + ttsengine_info_s* temp; + temp = (ttsengine_info_s*)g_malloc0(sizeof(ttsengine_info_s)); + + /* get engine info */ + if (0 != get_engine_info(&__engine_info_cb, (void*)temp)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to get engine info\n"); + dlclose(handle); + g_free(temp); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* close engine */ + dlclose(handle); + + temp->engine_path = g_strdup(filepath); + + SLOG(LOG_DEBUG, TAG_TTSD, "----- Valid engine"); + SLOG(LOG_DEBUG, TAG_TTSD, "Engine uuid : %s\n", temp->engine_uuid); + SLOG(LOG_DEBUG, TAG_TTSD, "Engine name : %s\n", temp->engine_name); + SLOG(LOG_DEBUG, TAG_TTSD, "Setting ug path : %s\n", temp->setting_ug_path); + SLOG(LOG_DEBUG, TAG_TTSD, "Engine path : %s\n", temp->engine_path); + SLOG(LOG_DEBUG, TAG_TTSD, "Use network : %s\n", temp->use_network ? "true":"false"); + SLOG(LOG_DEBUG, TAG_TTSD, "-----"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + *info = temp; + + return 0; +} + +int __internal_update_engine_list() +{ + /* relsease engine list */ + GList *iter = NULL; + ttsengine_info_s *data = NULL; + + if (g_list_length(g_engine_list) > 0) { + iter = g_list_first(g_engine_list); + + while (NULL != iter) { + data = iter->data; + + if (data != NULL) + g_free(data); + + g_engine_list = g_list_remove_link(g_engine_list, iter); + iter = g_list_first(g_engine_list); + } + } + + /* get file name from engine directory and get engine information from each filename */ + DIR *dp; + struct dirent *dirp; + dp = opendir(ENGINE_DIRECTORY); + + if (dp == NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] __internal_update_engine_list : error opendir \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] Search TTS Engines"); + + while ((dirp = readdir(dp)) != NULL) { + ttsengine_info_s* info; + char* filepath = NULL; + int file_size; + + file_size = strlen(ENGINE_DIRECTORY) + strlen(dirp->d_name) + 5; + filepath = (char*)g_malloc0( sizeof(char) * file_size); + + if (NULL != filepath) { + strncpy(filepath, ENGINE_DIRECTORY, strlen(ENGINE_DIRECTORY) ); + strncat(filepath, "/", strlen("/") ); + strncat(filepath, dirp->d_name, strlen(dirp->d_name) ); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not enough memory!! \n" ); + continue; + } + + /* get its info and update engine list */ + if (0 == __internal_get_engine_info(filepath, &info)) { + /* add engine info to g_engine_list */ + g_engine_list = g_list_append(g_engine_list, info); + } + + if (NULL != filepath) + g_free(filepath); + } + + closedir(dp); + + if (g_list_length(g_engine_list) <= 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] No Engine\n"); + return TTSD_ERROR_OPERATION_FAILED; + } + +#ifdef ENGINE_AGENT_DEBUG + ttsd_print_enginelist(); +#endif + + return 0; +} + +int __internal_set_current_engine(const char* engine_uuid) +{ + /* check whether engine id is valid or not. */ + GList *iter = NULL; + ttsengine_info_s *data = NULL; + + bool flag = false; + if (g_list_length(g_engine_list) > 0) { + iter = g_list_first(g_engine_list); + + while (NULL != iter) { + data = iter->data; + + if (0 == strncmp(data->engine_uuid, engine_uuid, strlen(engine_uuid))) { + flag = true; + break; + } + + /*Get next item*/ + iter = g_list_next(iter); + } + } + + /* If current engine does not exist, return error */ + if (false == flag) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] __internal_set_current_engine : Cannot find engine id \n"); + return TTSD_ERROR_OPERATION_FAILED; + } else { + if (g_cur_engine.engine_uuid != NULL) { + /*compare current engine uuid */ + if (0 == strncmp(g_cur_engine.engine_uuid, data->engine_uuid, strlen(engine_uuid))) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] tts engine has already been set \n"); + return 0; + } + } + } + + /* set data from g_engine_list */ + if (g_cur_engine.engine_uuid != NULL) g_free(g_cur_engine.engine_uuid); + if (g_cur_engine.engine_name != NULL) g_free(g_cur_engine.engine_name); + if (g_cur_engine.engine_path != NULL) g_free(g_cur_engine.engine_path); + + g_cur_engine.engine_uuid = g_strdup(data->engine_uuid); + g_cur_engine.engine_name = g_strdup(data->engine_name); + g_cur_engine.engine_path = g_strdup(data->engine_path); + + g_cur_engine.handle = NULL; + g_cur_engine.is_loaded = false; + g_cur_engine.is_set = true; + g_cur_engine.need_network = data->use_network; + + SLOG(LOG_DEBUG, TAG_TTSD, "-----"); + SLOG(LOG_DEBUG, TAG_TTSD, "Current engine uuid : %s \n", g_cur_engine.engine_uuid); + SLOG(LOG_DEBUG, TAG_TTSD, "Current engine name : %s \n", g_cur_engine.engine_name); + SLOG(LOG_DEBUG, TAG_TTSD, "Current engine path : %s \n", g_cur_engine.engine_path); + SLOG(LOG_DEBUG, TAG_TTSD, "-----"); + + return 0; +} + +int ttsd_engine_agent_load_current_engine() +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_set) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] ttsd_engine_agent_load_current_engine : No Current Engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* check whether current engine is loaded or not */ + if (true == g_cur_engine.is_loaded ) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent] ttsd_engine_agent_load_current_engine : Engine has already been loaded \n" ); + return 0; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] current engine path : %s\n", g_cur_engine.engine_path); + + /* open engine */ + char *error = NULL; + g_cur_engine.handle = dlopen(g_cur_engine.engine_path, RTLD_LAZY); /* RTLD_LAZY RTLD_NOW*/ + + if ((error = dlerror()) != NULL || !g_cur_engine.handle) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to get current engine handle : dlopen error \n"); + return -2; + } + + g_cur_engine.ttsp_unload_engine = (int (*)())dlsym(g_cur_engine.handle, "ttsp_unload_engine"); + if ((error = dlerror()) != NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to link daemon to ttsp_unload_engine() of current engine\n"); + return -3; + } + + g_cur_engine.ttsp_load_engine = (int (*)(const ttspd_funcs_s* , ttspe_funcs_s*) )dlsym(g_cur_engine.handle, "ttsp_load_engine"); + if ((error = dlerror()) != NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to link daemon to ttsp_load_engine() of current engine \n"); + return -3; + } + + /* load engine */ + g_cur_engine.pdfuncs->version = 1; + g_cur_engine.pdfuncs->size = sizeof(ttspd_funcs_s); + + int ret = 0; + ret = g_cur_engine.ttsp_load_engine(g_cur_engine.pdfuncs, g_cur_engine.pefuncs); + if (0 != ret) { + printf("Fail load '%s' engine\n", g_cur_engine.engine_path); + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to load engine : result(%d) \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] engine info : version(%d), size(%d)\n",g_cur_engine.pefuncs->version, g_cur_engine.pefuncs->size ); + + /* engine error check */ + if (g_cur_engine.pefuncs->size != sizeof(ttspe_funcs_s)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] ttsd_engine_agent_load_current_engine : current engine is not valid \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* initalize engine */ + if (NULL == g_cur_engine.pefuncs->initialize) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] init function of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + ret = g_cur_engine.pefuncs->initialize(__result_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to initialize current engine : result(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* select default voice */ + bool set_voice = false; + if (NULL != g_cur_engine.default_lang) { + if (NULL == g_cur_engine.pefuncs->is_valid_voice) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] is_valid_voice() of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (true == g_cur_engine.pefuncs->is_valid_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype)) { + set_voice = true; + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] Set origin default voice to current engine : lang(%s), type(%d) \n", + g_cur_engine.default_lang, g_cur_engine.default_vctype); + } else { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent WARNING] Fail set origin default voice : lang(%s), type(%d)\n", + g_cur_engine.default_lang, g_cur_engine.default_vctype); + } + } + + if (false == set_voice) { + if (NULL == g_cur_engine.pefuncs->foreach_voices) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] get_voice_list of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* get language list */ + int ret; + GList* voice_list = NULL; + + ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list); + + if (0 == ret && 0 < g_list_length(voice_list)) { + GList *iter = NULL; + voice_s* voice; + + iter = g_list_first(voice_list); + + if (NULL != iter) { + voice = iter->data; + + if (true != g_cur_engine.pefuncs->is_valid_voice(voice->language, voice->type)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine ERROR] Fail voice is NOT valid"); + return TTSD_ERROR_OPERATION_FAILED; + } + + ttsd_config_set_char_type(CONFIG_KEY_DEFAULT_LANGUAGE, voice->language); + ttsd_config_set_int_type(CONFIG_KEY_DEFAULT_VOICE_TYPE, voice->type); + + g_cur_engine.default_lang = g_strdup(voice->language); + g_cur_engine.default_vctype = voice->type; + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] Select default voice : lang(%s), type(%d) \n", + voice->language, voice->type); + + + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine ERROR] Fail to get language list : result(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + __free_voice_list(voice_list); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine ERROR] Fail to get language list : result(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + g_cur_engine.is_loaded = true; + + return 0; +} + +int ttsd_engine_agent_unload_current_engine() +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_set) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] No Current Engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] Engine has already been unloaded \n" ); + return 0; + } + + /* shutdown engine */ + if (NULL == g_cur_engine.pefuncs->deinitialize) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] The deinitialize() of engine is NULL!!"); + } else { + int ret = 0; + ret = g_cur_engine.pefuncs->deinitialize(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent] Fail deinitialize() : result(%d)\n", ret); + } + } + + /* unload engine */ + g_cur_engine.ttsp_unload_engine(); + + dlclose(g_cur_engine.handle); + + /* reset current engine data */ + g_cur_engine.handle = NULL; + g_cur_engine.is_loaded = false; + + return 0; +} + +bool ttsd_engine_agent_need_network() +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + return g_cur_engine.need_network; +} + +bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, ttsp_voice_type_e* out_type) +{ + if (NULL == lang || NULL == out_lang || NULL == out_type) { + return false; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] Select voice : input lang(%s) , input type(%d), default lang(%s), default type(%d)", + lang, type, g_cur_engine.default_lang, g_cur_engine.default_vctype); + + + /* case 1 : Both are default */ + if (0 == strncmp(lang, "default", strlen("default")) && 0 == type) { + *out_lang = strdup(g_cur_engine.default_lang); + *out_type = g_cur_engine.default_vctype; + return true; + + } + + /* Get voice list */ + if (NULL == g_cur_engine.pefuncs->foreach_voices) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] foreach_voices of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + GList* voice_list = NULL; + int ret = 0; + + ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list); + if (0 != ret || 0 >= g_list_length(voice_list)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to get voice list : result(%d) \n", ret); + return false; + } + + bool result; + result = false; + + GList *iter = NULL; + voice_s* voice; + + /* lang and type are not default type */ + if (0 != strncmp(lang, "default", strlen("default")) && 0 != type) { + iter = g_list_first(voice_list); + + while (NULL != iter) { + /* Get handle data from list */ + voice = iter->data; + + if (0 == strncmp(voice->language, lang, strlen(lang)) && voice->type == type) { + *out_lang = strdup(voice->language); + *out_type = voice->type; + result = true; + break; + } + + iter = g_list_next(iter); + } + + } else if (0 != strncmp(lang, "default", strlen("default")) && 0 == type) { + /* Only type is default */ + if (0 == strncmp(lang, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang))) { + *out_lang = strdup(g_cur_engine.default_lang); + *out_type = g_cur_engine.default_vctype; + result = true; + } else { + voice_s* voice_selected = NULL; + iter = g_list_first(voice_list); + while (NULL != iter) { + /* Get handle data from list */ + voice = iter->data; + + if (0 == strncmp(voice->language, lang, strlen(lang))) { + voice_selected = voice; + if (voice->type == g_cur_engine.default_vctype) { + voice_selected = voice; + break; + } + } + iter = g_list_next(iter); + } + + if (NULL != voice_selected) { + *out_lang = strdup(voice_selected->language); + *out_type = voice_selected->type; + result = true; + } + } + } else if (0 == strncmp(lang, "default", strlen("default")) && 0 != type) { + /* Only lang is default */ + if (type == g_cur_engine.default_vctype) { + *out_lang = strdup(g_cur_engine.default_lang); + *out_type = g_cur_engine.default_vctype; + result = true; + } else { + voice_s* voice_selected = NULL; + iter = g_list_first(voice_list); + while (NULL != iter) { + /* Get handle data from list */ + voice = iter->data; + + if (0 == strncmp(voice->language, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang)) ) { + voice_selected = voice; + if (voice->type == type) { + voice_selected = voice; + break; + } + } + iter = g_list_next(iter); + } + + if (NULL != voice_selected) { + *out_lang = strdup(voice->language); + *out_type = voice_selected->type; + result = true; + } + } + } + + if (true == result) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] Selected voice : lang(%s), type(%d) \n", *out_lang, *out_type); + } + + __free_voice_list(voice_list); + + return result; +} + +bool ttsd_engine_agent_is_same_engine(const char* engine_id) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return false; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return false; + } + + /* compare current engine and engine id.*/ + if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) { + return true; + } + + return false; +} + +/****************************************************************************************** +* TTS Engine Interfaces for client +*******************************************************************************************/ + +int ttsd_engine_start_synthesis(const char* lang, const ttsp_voice_type_e vctype, const char* text, const int speed, void* user_param) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] start ttsd_engine_start_synthesis() \n"); + + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* select voice for default */ + char* temp_lang = NULL; + ttsp_voice_type_e temp_type; + if (true != ttsd_engine_select_valid_voice(lang, vctype, &temp_lang, &temp_type)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Fail to select default voice \n"); + return TTSD_ERROR_INVALID_VOICE; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] Start synthesis : language(%s), type(%d), speed(%d), text(%s) \n", + temp_lang, temp_type, speed, text); + } + + if (NULL == g_cur_engine.pefuncs->start_synth) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] start_synth() of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + ttsp_speed_e temp_speed; + + if (0 == speed) { + temp_speed = g_cur_engine.default_speed; + } else { + temp_speed = speed; + } + + /* synthesize text */ + int ret = 0; + ret = g_cur_engine.pefuncs->start_synth(temp_lang, temp_type, text, temp_speed, user_param); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] ***************************************", ret); + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] * synthesize error : result(%6d) *", ret); + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] ***************************************", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == temp_lang) + free(temp_lang); + + return 0; +} + + +int ttsd_engine_cancel_synthesis() +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] start ttsd_engine_cancel_synthesis() \n"); + + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == g_cur_engine.pefuncs->cancel_synth) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] cancel_synth() of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* stop synthesis */ + int ret = 0; + ret = g_cur_engine.pefuncs->cancel_synth(); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail cancel synthesis : result(%d) \n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int ttsd_engine_get_audio_format( ttsp_audio_type_e* type, int* rate, int* channels) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == g_cur_engine.pefuncs->get_audio_format) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] get_audio_format() of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + int ret = 0; + ret = g_cur_engine.pefuncs->get_audio_format(type, rate, channels); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to get audio format : result(%d) \n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } else + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] get audio format : type(%d), rate(%d), channel(%d) \n", *type, *rate, *channels); + + return 0; +} + +bool __supported_voice_cb(const char* language, ttsp_voice_type_e type, void* user_data) +{ + GList** voice_list = (GList**)user_data; + + if (NULL == language || NULL == voice_list) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!"); + return false; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "-- Language(%s), Type(%d)", language, type); + + voice_s* voice = g_malloc0(sizeof(voice_s)); + voice->language = strdup(language); + voice->type = type; + + *voice_list = g_list_append(*voice_list, voice); + + return true; +} + +int ttsd_engine_get_voice_list(GList** voice_list) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == g_cur_engine.pefuncs->foreach_voices) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] The function of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + int ret = 0; + ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, (void*)voice_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Fail to get voice list : result(%d) \n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int ttsd_engine_get_default_voice( char** lang, ttsp_voice_type_e* vctype ) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == lang || NULL == vctype) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] BAD Parameter \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (NULL != g_cur_engine.default_lang) { + *lang = g_strdup(g_cur_engine.default_lang); + *vctype = g_cur_engine.default_vctype; + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine] Get default voice : language(%s), type(%d)\n", *lang, *vctype); + } else { + if (NULL == g_cur_engine.pefuncs->foreach_voices) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] get_voice_list of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* get language list */ + int ret; + GList* voice_list = NULL; + + ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list); + + if (0 == ret && 0 < g_list_length(voice_list)) { + GList *iter = NULL; + voice_s* voice; + + iter = g_list_first(voice_list); + + if (NULL != iter) { + voice = iter->data; + + if (true != g_cur_engine.pefuncs->is_valid_voice(voice->language, voice->type)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine ERROR] Fail voice is NOT valid "); + return TTSD_ERROR_OPERATION_FAILED; + } + + ttsd_config_set_char_type(CONFIG_KEY_DEFAULT_LANGUAGE, voice->language); + ttsd_config_set_int_type(CONFIG_KEY_DEFAULT_VOICE_TYPE, voice->type); + + if (NULL != g_cur_engine.default_lang) + g_free(g_cur_engine.default_lang); + + g_cur_engine.default_lang = g_strdup(voice->language); + g_cur_engine.default_vctype = voice->type; + + *lang = g_strdup(g_cur_engine.default_lang); + *vctype = g_cur_engine.default_vctype = voice->type; + + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine] Get default voice (New selected) : language(%s), type(%d)\n", *lang, *vctype); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine ERROR] Fail to get language list : result(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + __free_voice_list(voice_list); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine ERROR] Fail to get language list : result(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + return 0; +} + +/* +* TTS Engine Interfaces for setting +*/ +int ttsd_engine_setting_get_engine_list(GList** engine_list) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == engine_list) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Input parameter is NULL" ); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* update engine list */ + if (0 != __internal_update_engine_list()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail __internal_update_engine_list() \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + GList *iter = NULL; + ttsengine_info_s *data = NULL; + + iter = g_list_first(g_engine_list); + + SLOG(LOG_DEBUG, TAG_TTSD, "----- [Engine Agent] engine list -----"); + + while (NULL != iter) { + engine_s* temp_engine; + + temp_engine = (engine_s*)g_malloc0(sizeof(engine_s)); + + data = iter->data; + + temp_engine->engine_id = strdup(data->engine_uuid); + temp_engine->engine_name = strdup(data->engine_name); + temp_engine->ug_name = strdup(data->setting_ug_path); + + *engine_list = g_list_append(*engine_list, temp_engine); + + iter = g_list_next(iter); + + SLOG(LOG_DEBUG, TAG_TTSD, " -- engine id(%s) engine name(%s) ug name(%s) \n", + temp_engine->engine_id, temp_engine->engine_name, temp_engine->ug_name); + + } + + SLOG(LOG_DEBUG, TAG_TTSD, "--------------------------------------"); + + return 0; +} + +int ttsd_engine_setting_get_engine(char** engine_id) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_ENGINE_NOT_FOUND; + } + + *engine_id = strdup(g_cur_engine.engine_uuid); + + return 0; +} + +int ttsd_engine_setting_set_engine(const char* engine_id) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* compare current engine and new engine.*/ + if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent] new engine(%s) is the same as current engine(%s) \n", engine_id, g_cur_engine.engine_uuid); + return 0; + } + + char* tmp_uuid = NULL; + tmp_uuid = strdup(g_cur_engine.engine_uuid); + + /* unload engine */ + if (0 != ttsd_engine_agent_unload_current_engine()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent Error] fail to unload current engine \n"); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] unload current engine \n"); + } + + /* change current engine */ + if (0 != __internal_set_current_engine(engine_id)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail __internal_set_current_engine() \n"); + + /* roll back to old current engine. */ + __internal_set_current_engine(tmp_uuid); + + if( tmp_uuid != NULL ) + free(tmp_uuid); + + return TTSD_ERROR_OPERATION_FAILED; + } + + /* load engine */ + if (0 != ttsd_engine_agent_load_current_engine()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent Error] fail to load new engine \n"); + + if( tmp_uuid != NULL ) + free(tmp_uuid); + + return TTSD_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] load new engine \n"); + } + + /* save engine id to config */ + if (0 != ttsd_config_set_char_type(CONFIG_KEY_DEFAULT_ENGINE_ID, engine_id)) { + SLOG(LOG_WARN, TAG_TTSD, "[Engine Agent WARNING] Fail to save engine id to config \n"); + } + + if (tmp_uuid != NULL) + free(tmp_uuid); + + return 0; +} + +int ttsd_engine_setting_get_voice_list(char** engine_id, GList** voice_list) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + int ret = 0; + + /* get language list from engine*/ + ret = ttsd_engine_get_voice_list(voice_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Error] fail ttsd_engine_get_voice_list() \n"); + return ret; + } + + *engine_id = strdup(g_cur_engine.engine_uuid); + + return 0; +} + +int ttsd_engine_setting_get_default_voice(char** language, ttsp_voice_type_e* vctype) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* get current language from engine*/ + int ret = 0; + char* temp_lang; + ttsp_voice_type_e temp_int; + + ret = ttsd_engine_get_default_voice(&temp_lang, &temp_int); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Error] fail ttsd_engine_get_default_voice() \n"); + return ret; + } + + if (NULL != temp_lang) { + *language = strdup(temp_lang); + *vctype = temp_int; + free(temp_lang); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Error] fail to get default language \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int ttsd_engine_setting_set_default_voice(const char* language, ttsp_voice_type_e vctype) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == g_cur_engine.pefuncs->is_valid_voice) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] The function of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + int ret = -1; + if(false == g_cur_engine.pefuncs->is_valid_voice(language, vctype)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Voice is NOT valid !!"); + return TTSD_ERROR_INVALID_VOICE; + } + + if (NULL != g_cur_engine.default_lang) + free(g_cur_engine.default_lang); + + g_cur_engine.default_lang = strdup(language); + g_cur_engine.default_vctype = vctype; + + ret = ttsd_config_set_char_type(CONFIG_KEY_DEFAULT_LANGUAGE, language); + if (0 == ret) { + ret = ttsd_config_set_int_type(CONFIG_KEY_DEFAULT_VOICE_TYPE, vctype); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to write default voice to config (%d) \n", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Engine Agent SUCCESS] Set default voice : lang(%s), type(%d) \n", + g_cur_engine.default_lang, g_cur_engine.default_vctype); + } + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to write default voice to config (%d) \n", ret); + } + + return 0; +} + +int ttsd_engine_setting_get_default_speed(ttsp_speed_e* speed) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* get current language */ + *speed = g_cur_engine.default_speed; + + return 0; +} + +int ttsd_engine_setting_set_default_speed(const ttsp_speed_e speed) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + g_cur_engine.default_speed = speed; + + if (0 != ttsd_config_set_int_type(CONFIG_KEY_DEFAULT_SPEED, speed)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to set default speed to config"); + } + + return 0; +} + +bool __engine_setting_cb(const char* key, const char* value, void* user_data) +{ + GList** engine_setting_list = (GList**)user_data; + + if (NULL == engine_setting_list || NULL == key || NULL == value) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Input parameter is NULL in engine setting callback!!!!"); + return false; + } + + engine_setting_s* temp = g_malloc0(sizeof(engine_setting_s)); + temp->key = g_strdup(key); + temp->value = g_strdup(value); + + *engine_setting_list = g_list_append(*engine_setting_list, temp); + + return true; +} + + +int ttsd_engine_setting_get_engine_setting_info(char** engine_id, GList** setting_list) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == setting_list) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Input parameter is NULL"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (NULL == g_cur_engine.pefuncs->foreach_engine_setting) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] foreach_engine_setting() of engine is NULL!!"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* get setting info and move setting info to input parameter */ + int result = 0; + + result = g_cur_engine.pefuncs->foreach_engine_setting(__engine_setting_cb, setting_list); + + if (0 == result && 0 < g_list_length(*setting_list)) { + *engine_id = strdup(g_cur_engine.engine_uuid); + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to get setting info : result(%d)\n", result); + result = TTSD_ERROR_OPERATION_FAILED; + } + + return result; +} + +int ttsd_engine_setting_set_engine_setting(const char* key, const char* value) +{ + if (false == g_agent_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not Initialized \n" ); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (false == g_cur_engine.is_loaded) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] Not loaded engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (NULL == g_cur_engine.pefuncs->set_engine_setting) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] set_setting_info of engine is NULL!! \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* get setting info and move setting info to input parameter */ + int ret = 0; + ret = g_cur_engine.pefuncs->set_engine_setting(key, value); + + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Engine Agent ERROR] fail to set engine setting : result(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + return 0; +} + +void __free_voice_list(GList* voice_list) +{ + GList *iter = NULL; + voice_s* data = NULL; + + /* if list have item */ + if (g_list_length(voice_list) > 0) { + /* Get a first item */ + iter = g_list_first(voice_list); + + while (NULL != iter) { + data = iter->data; + + if (NULL != data->language) + g_free(data->language); + if (NULL != data); + g_free(data); + + voice_list = g_list_remove_link(voice_list, iter); + + iter = g_list_first(voice_list); + } + } +} + +/* +* TTS Engine Callback Functions ` * +*/ +bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, void *user_data) +{ + g_result_cb(event, data, data_size, user_data); + + return true; +} + +/* function for debugging */ +int ttsd_print_enginelist() +{ + GList *iter = NULL; + ttsengine_info_s *data = NULL; + + if (g_list_length(g_engine_list) > 0) { + iter = g_list_first(g_engine_list); + + SLOG(LOG_DEBUG, TAG_TTSD, "----- engine list -----"); + + int i = 1; + while (NULL != iter) { + data = iter->data; + + SLOG(LOG_DEBUG, TAG_TTSD, "[%dth]\n", i); + SLOG(LOG_DEBUG, TAG_TTSD, "engine uuid : %s\n", data->engine_uuid); + SLOG(LOG_DEBUG, TAG_TTSD, "engine name : %s\n", data->engine_name); + SLOG(LOG_DEBUG, TAG_TTSD, "engine path : %s\n", data->engine_path); + SLOG(LOG_DEBUG, TAG_TTSD, "setting ug path : %s\n", data->setting_ug_path); + + iter = g_list_next(iter); + i++; + } + SLOG(LOG_DEBUG, TAG_TTSD, "-----------------------"); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "----- engine list -----"); + SLOG(LOG_DEBUG, TAG_TTSD, "No Engine in directory"); + SLOG(LOG_DEBUG, TAG_TTSD, "-----------------------"); + } + + return 0; +} + + + + + + + diff --git a/server/ttsd_engine_agent.h b/server/ttsd_engine_agent.h new file mode 100644 index 0000000..dfccf33 --- /dev/null +++ b/server/ttsd_engine_agent.h @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2011 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_ENGINE_AGENT_H_ +#define __TTSD_ENGINE_AGENT_H_ + +#include "ttsd_main.h" +#include "ttsd_player.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*synth_result_callback)(ttsp_result_event_e event, const void* data, unsigned int data_size, void *user_data); + +/* +* tts Engine Agent Interfaces +*/ + +/** Init engine agent */ +int ttsd_engine_agent_init(synth_result_callback result_cb); + +/** Release engine agent */ +int ttsd_engine_agent_release(); + +/** Set current engine */ +int ttsd_engine_agent_initialize_current_engine(); + +/** load current engine */ +int ttsd_engine_agent_load_current_engine(); + +/** Unload current engine */ +int ttsd_engine_agent_unload_current_engine(); + +/** test for language list */ +int ttsd_print_enginelist(); + +/** Get state of current engine to need network */ +bool ttsd_engine_agent_need_network(); + +bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, ttsp_voice_type_e* out_type); + +bool ttsd_engine_agent_is_same_engine(const char* engine_id); + +/* +* TTS Engine Interfaces for client +*/ +int ttsd_engine_start_synthesis(const char* lang, const ttsp_voice_type_e vctype, const char* text, const int speed, void* user_param); + +int ttsd_engine_cancel_synthesis(); + +int ttsd_engine_get_voice_list(GList** voice_list); + +int ttsd_engine_get_default_voice(char** lang, ttsp_voice_type_e* vctype ); + +int ttsd_engine_get_audio_format(ttsp_audio_type_e* type, int* rate, int* channels); + +/* +* TTS Engine Interfaces for setting +*/ + +/** Get engine list */ +int ttsd_engine_setting_get_engine_list(GList** engine_list); + +/** Get engine */ +int ttsd_engine_setting_get_engine(char** engine_id); + +/** Set engine */ +int ttsd_engine_setting_set_engine(const char* engine_id); + +/** Get voice list for engine setting */ +int ttsd_engine_setting_get_voice_list(char** engine_id, GList** voice_list); + +/** Get default voice */ +int ttsd_engine_setting_get_default_voice(char** language, ttsp_voice_type_e* vctype); + +/** Set voice for engine setting */ +int ttsd_engine_setting_set_default_voice(const char* language, ttsp_voice_type_e vctype); + +/** Get voice speed for engine setting */ +int ttsd_engine_setting_get_default_speed(ttsp_speed_e* speed); + +/** Set voice speed for engine setting */ +int ttsd_engine_setting_set_default_speed(ttsp_speed_e speed); + +/** Get setting info */ +int ttsd_engine_setting_get_engine_setting_info(char** engine_id, GList** setting_list); + +/** Set setting info */ +int ttsd_engine_setting_set_engine_setting(const char* key, const char* value); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_ENGINE_AGENT_H_ */ diff --git a/server/ttsd_main.c b/server/ttsd_main.c new file mode 100644 index 0000000..0157760 --- /dev/null +++ b/server/ttsd_main.c @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2011 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 "ttsd_server.h" +#include "ttsd_dbus.h" +#include "ttsd_network.h" + +#include + +/* Main of TTS Daemon */ +int main() +{ + SLOG(LOG_DEBUG, TAG_TTSD, " "); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + SLOG(LOG_DEBUG, TAG_TTSD, "===== TTS DAEMON INITIALIZE"); + if (!ecore_init()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Main ERROR] fail ecore_init() \n"); + return -1; + } + + if (0 != ttsd_initialize()) { + printf("Fail to initialize tts-daemon \n"); + SLOG(LOG_ERROR, TAG_TTSD, "[Main ERROR] fail to initialize tts-daemon \n"); + return EXIT_FAILURE; + } + + if (0 != ttsd_dbus_open_connection()) { + printf("Fail to initialize IPC connection \n"); + SLOG(LOG_ERROR, TAG_TTSD, "[Main ERROR] fail to open dbus connection \n"); + return EXIT_FAILURE; + } + + if (0 != ttsd_network_initialize()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Main ERROR] fail to initialize network \n"); + return EXIT_FAILURE; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Main] tts-daemon start...\n"); + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + printf("TTS-Daemon Start...\n"); + + ecore_main_loop_begin(); + + ecore_shutdown(); + + ttsd_dbus_close_connection(); + + ttsd_network_finalize(); + + return 0; +} + diff --git a/server/ttsd_main.h b/server/ttsd_main.h new file mode 100644 index 0000000..1d0df35 --- /dev/null +++ b/server/ttsd_main.h @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2011 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_MAIN_H_ +#define __TTSD_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ttsp.h" +#include "tts_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* TTS Daemon Define */ +#define TAG_TTSD "ttsd" +#define ENGINE_DIRECTORY "/usr/lib/voice/tts/1.0/engine" + +/* for debug message */ +#define DATA_DEBUG + +typedef enum { + TTSD_ERROR_NONE = 0, /**< Success, No error */ + TTSD_ERROR_OUT_OF_MEMORY = -ENOMEM, /**< Out of Memory */ + TTSD_ERROR_IO_ERROR = -EIO, /**< I/O error */ + TTSD_ERROR_INVALID_PARAMETER = -EINVAL, /**< Invalid parameter */ + TTSD_ERROR_INVALID_STATE = -0x0100021, /**< Invalid state */ + TTSD_ERROR_INVALID_VOICE = -0x0100022, /**< Invalid voice */ + TTSD_ERROR_ENGINE_NOT_FOUND = -0x0100023, /**< No available TTS-engine */ + TTSD_ERROR_TIMED_OUT = -0x0100024, /**< No answer from TTS daemon */ + TTSD_ERROR_OPERATION_FAILED = -0x0100025, /**< TTS daemon failed */ +}ttsd_error_e; + + +typedef enum { + TTSD_INTERRUPTED_PAUSED = 0, /**< Current state change 'Pause' */ + TTSD_INTERRUPTED_STOPPED /**< Current state change 'Ready' */ +}ttsd_interrupted_code_e; + + +typedef struct { + char* engine_id; + char* engine_name; + char* ug_name; +}engine_s; + +typedef struct { + char* language; + ttsp_voice_type_e type; +}voice_s; + +typedef struct { + char* key; + char* value; +}engine_setting_s; + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_MAIN_H_ */ diff --git a/server/ttsd_network.c b/server/ttsd_network.c new file mode 100644 index 0000000..cc1febf --- /dev/null +++ b/server/ttsd_network.c @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2011 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 "ttsd_network.h" + +#include + +bool g_is_connected; + +bool ttsd_network_is_connected() +{ + return g_is_connected; +} + +void __net_config_change_cb(keynode_t* node, void *data) +{ + int network_configuration = 0; + vconf_get_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND , &network_configuration); + SLOG(LOG_DEBUG, TAG_TTSD, "[Network DEBUG] Network configuration : %d", network_configuration); + + if (network_configuration == 0) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Network] Notification : Network connection is OFF "); + g_is_connected = false; + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Network] Notification : Network connection is ON "); + g_is_connected = true; + + /* need to notify changing net to engine. */ + } + + return; +} + +int ttsd_network_initialize() +{ + int network_configuration = 0; + vconf_get_int(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND , &network_configuration); + SLOG(LOG_DEBUG, TAG_TTSD, "[Network DEBUG] Network configuration : %d", network_configuration); + + if (network_configuration == 0) { + /* "0" means the network configuration is not set. + * It could be network connection is not open + */ + + int network_status = 0; + vconf_get_int(VCONFKEY_NETWORK_STATUS, &network_status); + + if(network_status == VCONFKEY_NETWORK_OFF){ + printf("Current network connection is OFF!! \n"); + SLOG(LOG_DEBUG, TAG_TTSD, "[Network] Current network connection is OFF."); + } + else{ + /* + * This is the problem of network connection + * Just terminate the application, network f/w will fix the problem automatically. + */ + printf("network status is wrong or IP is not set\n"); + printf("network has problem, try again\n"); + return -1; + } + + g_is_connected = false; + } else { + printf("Current network connection is ON. \n"); + SLOG(LOG_DEBUG, TAG_TTSD, "[Network] Current network connection is ON."); + + g_is_connected = true; + } + + vconf_notify_key_changed(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, __net_config_change_cb, NULL); + + SLOG(LOG_DEBUG, TAG_TTSD, "[Network SUCCESS] Initialize network ...\n"); + + return 0; +} + +int ttsd_network_finalize() +{ + vconf_ignore_key_changed(VCONFKEY_NETWORK_CONFIGURATION_CHANGE_IND, __net_config_change_cb); + + return 0; +} + diff --git a/server/ttsd_network.h b/server/ttsd_network.h new file mode 100644 index 0000000..a1eaf92 --- /dev/null +++ b/server/ttsd_network.h @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2011 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_NETWORK_H_ +#define __TTSD_NETWORK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int ttsd_network_initialize(); + +int ttsd_network_finalize(); + +bool ttsd_network_is_connected(); + + +#ifdef __cplusplus +} +#endif + + +#endif /* __TTSD_NETWORK_H_ */ diff --git a/server/ttsd_player.cpp b/server/ttsd_player.cpp new file mode 100644 index 0000000..02a825c --- /dev/null +++ b/server/ttsd_player.cpp @@ -0,0 +1,990 @@ +/* +* Copyright (c) 2011 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 +#include + +#include "ttsd_main.h" +#include "ttsd_player.h" +#include "ttsd_data.h" +#include "ttsd_dbus.h" + + +/* +* Internal data structure +*/ + +#define TEMP_FILE_MAX 36 + +typedef struct { + char riff[4]; + int file_size; + char wave[4]; + char fmt[4]; + int header_size; + short sample_format; + short n_channels; + int sample_rate; + int bytes_per_second; + short block_align; + short bits_per_sample; + char data[4]; + int data_size; +} WavHeader; + +typedef struct { + int uid; /** client id */ + MMHandleType player_handle; /** mm player handle */ + int utt_id; /** utt_id of next file */ + ttsp_result_event_e event; /** event of callback */ +} player_s; + +typedef struct { + int uid; + int utt_id; + ttsp_result_event_e event; + char filename[TEMP_FILE_MAX]; +} user_data_s; + + +/* +* static data +*/ + +#define TEMP_FILE_PATH "/tmp" +#define FILE_PATH_SIZE 256 + +/** player init info */ +static bool g_player_init = false; + +/** tts engine list */ +static GList *g_player_list; + +/** current player information */ +static player_s* g_playing_info; + +/** player callback function */ +static player_result_callback_func g_result_callback; + +/** numbering for temp file */ +static unsigned int g_index; + + +/* +* Internal Interfaces +*/ + +player_s* __player_get_item(int uid); + +int __save_file(const int uid, const int index, const sound_data_s data, char** filename); + +int __set_and_start(player_s* player); + +int __init_wave_header(WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel); + +static int msg_callback(int message, void *data, void *user_param) ; + + +/* +* Player Interfaces +*/ + +int ttsd_player_init(player_result_callback_func result_cb) +{ + if (NULL == result_cb) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] invalid parameter"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + g_result_callback = result_cb; + + g_playing_info = NULL; + + g_index = 1; + g_player_init = true; + + return 0; +} + +int ttsd_player_release(void) +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* clear g_player_list */ + g_playing_info = NULL; + g_player_init = false; + + return 0; +} + +int ttsd_player_create_instance(const int uid) +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + /* Check uid is duplicated */ + if (NULL != __player_get_item(uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is already registered", uid); + return -1; + } + + int ret = MM_ERROR_NONE; + MMHandleType player_handle; + + ret = mm_player_create(&player_handle); + if (ret != MM_ERROR_NONE || 0 == player_handle) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_create() : %x", ret); + return -2; + } + + player_s* new_client = (player_s*)g_malloc0( sizeof(player_s) * 1); + + new_client->uid = uid; + new_client->player_handle = player_handle; + new_client->utt_id = -1; + new_client->event = TTSP_RESULT_EVENT_FINISH; + + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] Create player : uid(%d), handle(%d)", uid, player_handle ); + + g_player_list = g_list_append(g_player_list, new_client); + + return 0; +} + + +int ttsd_player_destroy_instance(int uid) +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is not valid", uid); + return -1; + } + + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + g_playing_info = NULL; + } + } + + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] State changed : state(%d)", player_state); + + int ret = -1; + /* destroy player */ + switch (player_state) { + case MM_PLAYER_STATE_PLAYING: + case MM_PLAYER_STATE_PAUSED: + ret = mm_player_stop(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player WARNING] fail mm_player_stop() : %x", ret); + } + /* NO break for unrealize */ + + case MM_PLAYER_STATE_READY: + ret = mm_player_unrealize(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_unrealize() : %x", ret); + } + /* NO break for destroy */ + + case MM_PLAYER_STATE_NULL: + mm_player_destroy(current->player_handle); + break; + + default: + break; + } + + GList *iter = NULL; + player_s *data = NULL; + + if (0 < g_list_length(g_player_list)) { + /* Get a first item */ + iter = g_list_first(g_player_list); + + while (NULL != iter) { + /* Get handle data from list */ + data = (player_s*)iter->data; + + /* compare uid */ + if (uid == data->uid) { + g_player_list = g_list_remove_link(g_player_list, iter); + if (NULL != data) { + g_free(data); + } + break; + } + + /* Get next item */ + iter = g_list_next(iter); + } + } + + return 0; +} + +int ttsd_player_play(const int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] start play : uid(%d)", uid ); + + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] uid(%d) has already played", g_playing_info->uid); + return 0; + } + } + + /* Check sound queue size */ + if (0 == ttsd_data_get_sound_data_size(uid)) { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] A sound queue of current player(%d) is empty", uid); + return -1; + } + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is not valid", uid); + return -1; + } + + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] State changed : state(%d)", player_state); + + switch (player_state) { + case MM_PLAYER_STATE_PLAYING: + SLOG(LOG_WARN, TAG_TTSD, "[Player] Current player is playing. Do not start new sound."); + return 0; + + case MM_PLAYER_STATE_PAUSED: + SLOG(LOG_WARN, TAG_TTSD, "[Player] Player is paused. Do not start new sound."); + return -1; + + case MM_PLAYER_STATE_READY: + SLOG(LOG_WARN, TAG_TTSD, "[Player] Player is ready for next play. Do not start new sound."); + return -1; + + case MM_PLAYER_STATE_NULL: + break; + + case MM_PLAYER_STATE_NONE: + SLOG(LOG_WARN, TAG_TTSD, "[Player] Player is created. Do not start new sound."); + return -1; + + default: + return -1; + } + + int ret; + ret = __set_and_start(current); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail to set or start mm_player"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] Started play and wait for played callback : uid(%d)", uid); + + return 0; +} + +int ttsd_player_next_play(int uid) +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is not valid", uid); + g_playing_info = NULL; + return -1; + } + + if (NULL != g_playing_info) { + if (uid != g_playing_info->uid) { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] Current player(%d) is NOT uid(%d)", g_playing_info->uid, uid); + return 0; + } + } else { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Current player do NOT exist"); + return -1; + } + + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] State changed : state(%d)", player_state); + + int ret = -1; + /* stop player */ + switch (player_state) { + case MM_PLAYER_STATE_PLAYING: + case MM_PLAYER_STATE_PAUSED: + ret = mm_player_stop(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player WARNING] fail mm_player_stop() : %x", ret); + } + /* NO break for unrealize */ + + case MM_PLAYER_STATE_READY: + ret = mm_player_unrealize(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_unrealize() : %x", ret); + return -1; + } + break; + + case MM_PLAYER_STATE_NULL: + break; + + default: + break; + } + + /* Check sound queue size */ + if (0 == ttsd_data_get_sound_data_size(uid)) { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] A sound queue of current player(%d) is empty", uid); + g_playing_info = NULL; + return -1; + } + + ret = __set_and_start(current); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail to set or start mm_player"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] Started play and wait for played callback : uid(%d)", uid); + + return 0; +} + + +int ttsd_player_stop(const int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] stop player : uid(%d)", uid ); + + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is not valid", uid); + return -1; + } + + /* check whether uid is current playing or not */ + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + /* release current playing info */ + g_playing_info = NULL; + } + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] No current playing"); + } + + current->utt_id = -1; + + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] Current state(%d)", player_state); + + int ret = -1; + switch (player_state) { + case MM_PLAYER_STATE_PLAYING: + case MM_PLAYER_STATE_PAUSED: + ret = mm_player_stop(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player WARNING] fail mm_player_stop() : %x", ret); + } + /* NO break for unrealize */ + + case MM_PLAYER_STATE_READY: + ret = mm_player_unrealize(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_unrealize() : %x", ret); + return -1; + } + break; + + case MM_PLAYER_STATE_NULL: + break; + + default: + break; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Player SUCCESS] Stop player : uid(%d)", uid); + + return 0; +} + +int ttsd_player_pause(const int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] pause player : uid(%d)", uid ); + + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid); + return -1; + } + + /* check whether uid is current playing or not */ + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + /* release current playing info */ + g_playing_info = NULL; + } else { + /* error case */ + } + } + + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] Current state(%d)", player_state); + + int ret = 0; + if (MM_PLAYER_STATE_PLAYING == player_state) { + ret = mm_player_pause(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_pause : %x ", ret); + } + } else { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] Current player is NOT 'playing'"); + } + + + return 0; +} + +int ttsd_player_resume(const int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] Resume player : uid(%d)", uid ); + + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + /* Check id */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is not valid", uid); + return -1; + } + + /* check current player */ + if (NULL != g_playing_info) + g_playing_info = NULL; + + + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] Current state(%d)", player_state); + + int ret = -1; + if (MM_PLAYER_STATE_PAUSED == player_state) { + ret = mm_player_resume(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_resume() : %d", ret); + return -1; + } + + g_playing_info = current; + } else { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] Current uid is NOT paused state."); + } + + return 0; +} + +int ttsd_player_get_current_client() +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + if (NULL != g_playing_info) + return g_playing_info->uid; + + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] No current player"); + + return 0; +} + +int ttsd_player_get_current_utterance_id(const int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "[Player] get current utt id : uid(%d)", uid ); + + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] uid(%d) is not valid", uid); + return -1; + } + + return current->utt_id; +} + +int ttsd_player_all_stop() +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Not Initialized" ); + return -1; + } + + g_playing_info = NULL; + + int ret = -1; + GList *iter = NULL; + player_s *data = NULL; + + if (0 < g_list_length(g_player_list)) { + /* Get a first item */ + iter = g_list_first(g_player_list); + + while (NULL != iter) { + /* Get handle data from list */ + data = (player_s*)iter->data; + + app_state_e state; + if (0 > ttsd_data_get_client_state(data->uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[player ERROR] ttsd_player_all_stop : uid is not valid "); + ttsd_player_destroy_instance(data->uid); + iter = g_list_next(iter); + continue; + } + + if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) { + ret = mm_player_stop(data->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_WARN, TAG_TTSD, "[player WARNING] fail mm_player_stop() : %x ", ret); + } + + /* unrealize player */ + ret = mm_player_unrealize(data->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_unrealize() : %x", ret); + } + + data->utt_id = -1; + data->event = TTSP_RESULT_EVENT_FINISH; + } + + /* Get next item */ + iter = g_list_next(iter); + } + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Player SUCCESS] player all stop!! "); + + return 0; +} + +static int msg_callback(int message, void *data, void *user_param) +{ + user_data_s* user_data; + + user_data = (user_data_s*)user_param; + + int uid = user_data->uid; + int utt_id = user_data->utt_id; + + switch (message) { + case MM_MESSAGE_ERROR: + { + SLOG(LOG_DEBUG, TAG_TTSD, "===== PLAYER ERROR CALLBACK"); + SLOG(LOG_ERROR, TAG_TTSD, "[PLAYER ERROR] Info : uid(%d), utt id(%d), error file(%s)", uid, utt_id, user_data->filename); + + /* send error info */ + g_result_callback(PLAYER_ERROR, uid, utt_id); + + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[PLAYER ERROR] uid(%d) is NOT valid ", uid); + } else { + current->event = TTSP_RESULT_EVENT_FINISH; + } + + if (NULL != user_data) + g_free(user_data); + + /* check current player */ + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + g_playing_info = NULL; + SLOG(LOG_WARN, TAG_TTSD, "[PLAYER] Current Player is NOT uid(%d)", uid); + } + } + + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + } + break; /*MM_MESSAGE_ERROR*/ + + case MM_MESSAGE_BEGIN_OF_STREAM: + { + SLOG(LOG_DEBUG, TAG_TTSD, "===== BEGIN OF STREAM CALLBACK"); + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[PLAYER] uid(%d) is NOT valid ", uid); + return -1; + } + + if (TTSP_RESULT_EVENT_START == user_data->event || + (TTSP_RESULT_EVENT_FINISH == current->event && TTSP_RESULT_EVENT_FINISH == user_data->event)) { + int pid; + pid = ttsd_data_get_pid(uid); + + /* send utterance start message */ + if (0 == ttsdc_send_utt_start_signal(pid, uid, utt_id)) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Send SUCCESS] Send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id); + } else + SLOG(LOG_ERROR, TAG_TTSD, "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] Don't need to send Utterance Start Signal"); + } + + /* set current playing info */ + current->utt_id = utt_id; + current->event = user_data->event; + g_playing_info = current; + + app_state_e state; + ttsd_data_get_client_state(uid, &state); + + /* for sync problem */ + if (APP_STATE_PAUSED == state) { + MMPlayerStateType player_state; + mm_player_get_state(current->player_handle, &player_state); + + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] Current state(%d)", player_state); + + int ret = 0; + if (MM_PLAYER_STATE_PLAYING == player_state) { + ret = mm_player_pause(current->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[PLAYER ERROR] fail mm_player_pause() : %x", ret); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[PLAYER] uid(%d) changes 'Pause' state ", uid); + } + } + } + + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + } + break; + + case MM_MESSAGE_END_OF_STREAM: + { + SLOG(LOG_DEBUG, TAG_TTSD, "===== END OF STREAM CALLBACK"); + remove(user_data->filename); + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, TAG_TTSD, "[PLAYER ERROR] uid(%d) is NOT valid", uid); + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + g_playing_info = NULL; + SLOG(LOG_WARN, TAG_TTSD, "[PLAYER] Current Player is NOT uid(%d)", uid); + } + } + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + return -1; + } + + if (NULL != user_data) + g_free(user_data); + + int pid = ttsd_data_get_pid(uid); + + /* send utterence finish signal */ + if (TTSP_RESULT_EVENT_FINISH == current->event) { + if (0 == ttsdc_send_utt_finish_signal(pid, uid, utt_id)) + SLOG(LOG_DEBUG, TAG_TTSD, "[Send SUCCESS] Send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id); + else + SLOG(LOG_ERROR, TAG_TTSD, "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id); + } + + ttsd_send_start_next_play(uid); + + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + } + break; /*MM_MESSAGE_END_OF_STREAM*/ + + case MM_MESSAGE_STATE_CHANGED: + break; + + default: + break; + } + + return TRUE; +} + +player_s* __player_get_item(int uid) +{ + GList *iter = NULL; + player_s *data = NULL; + + if (0 < g_list_length(g_player_list)) { + /* Get a first item */ + iter = g_list_first(g_player_list); + + while (NULL != iter) { + /* Get handle data from list */ + data = (player_s*)iter->data; + + /* compare uid */ + if (uid == data->uid) + return data; + + /* Get next item */ + iter = g_list_next(iter); + } + } + + return NULL; +} + +int __save_file(const int uid, const int index, const sound_data_s data, char** filename) +{ + char postfix[5]; + memset(postfix, 0, 5); + + switch (data.audio_type) { + case TTSP_AUDIO_TYPE_RAW: + case TTSP_AUDIO_TYPE_WAV: + strncpy(postfix, "wav", strlen("wav")); + break; + case TTSP_AUDIO_TYPE_MP3: + strncpy(postfix, "mp3", strlen("mp3")); + break; + case TTSP_AUDIO_TYPE_AMR: + strncpy(postfix, "amr", strlen("amr")); + break; + default: + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Audio type(%d) is NOT valid", data.audio_type); + return -1; + } + + /* make filename to save */ + char* temp; + temp = *filename; + + snprintf(temp, FILE_PATH_SIZE, "%s/ttstemp%d_%d.%s", TEMP_FILE_PATH, uid, index, postfix ); + + FILE* fp; + fp = fopen(temp, "wb"); + + if (fp == NULL) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] temp file open error"); + return -1; + } + + if (data.audio_type == TTSP_AUDIO_TYPE_RAW) { + WavHeader header; + if (0 != __init_wave_header(&header, data.data_size, data.rate, data.channels)) { + fclose(fp); + return -1; + } + + if (0 >= fwrite(&header, sizeof(WavHeader), 1, fp)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail to write wav header to file"); + fclose(fp); + return -1; + } + } + + int size = fwrite(data.data, data.data_size, 1, fp); + if (size <= 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Fail to write date"); + fclose(fp); + return -1; + } + + fclose(fp); + + SLOG(LOG_DEBUG, TAG_TTSD, " "); + SLOG(LOG_DEBUG, TAG_TTSD, "Filepath : %s ", temp); + SLOG(LOG_DEBUG, TAG_TTSD, "Header : Data size(%d), Sample rate(%d), Channel(%d) ", data.data_size, data.rate, data.channels); + + return 0; +} + +int __init_wave_header (WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel) +{ + if (hdr == NULL || nsamples <= 0 || sampling_rate <= 0 || channel <= 0) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] __init_wave_header : input parameter invalid"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + size_t bytesize = nsamples; + + strncpy(hdr->riff, "RIFF", 4); + hdr->file_size = (int)(bytesize + 36); + strncpy(hdr->wave, "WAVE", 4); + strncpy(hdr->fmt, "fmt ", 4); + hdr->header_size = 16; + hdr->sample_format = 1; /* WAVE_FORMAT_PCM */ + hdr->n_channels = channel; + hdr->sample_rate = (int)(sampling_rate); + hdr->bytes_per_second = (int)sampling_rate * sizeof(short); + hdr->block_align = sizeof(short); + hdr->bits_per_sample = sizeof(short)*8; + strncpy(hdr->data, "data", 4); + hdr->data_size = (int)bytesize; + + return 0; +} + +int __set_and_start(player_s* player) +{ + /* get sound data */ + sound_data_s wdata; + if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) { + SLOG(LOG_WARN, TAG_TTSD, "[Player WARNING] A sound queue of current player(%d) is empty", player->uid); + return -1; + } + + g_index++; + if (65534 <= g_index) { + g_index = 1; + } + + /* make sound file for mmplayer */ + char* sound_file = NULL; + sound_file = (char*) g_malloc0( sizeof(char) * FILE_PATH_SIZE ); + + if (0 != __save_file(player->uid, g_index, wdata, &sound_file)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail to make sound file"); + return -1; + } + + user_data_s* user_data = (user_data_s*)g_malloc0(sizeof(user_data_s)); + user_data->uid = player->uid; + user_data->utt_id = wdata.utt_id; + user_data->event = wdata.event; + memset(user_data->filename, 0, TEMP_FILE_MAX); + strncpy( user_data->filename, sound_file, strlen(sound_file) ); + + SLOG(LOG_DEBUG, TAG_TTSD, "Info : uid(%d), utt(%d), filename(%s) , event(%d)", + user_data->uid, user_data->utt_id, user_data->filename, user_data->event); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + int ret; + + /* set callback func */ + ret = mm_player_set_message_callback(player->player_handle, msg_callback, (void*)user_data); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Fail mm_player_set_message_callback() : %x ", ret); + return -1; + } + + /* set playing info to mm player */ + char* err_attr_name = NULL; + + if (0 != access(sound_file, R_OK)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Fail to read sound file (%s)", sound_file); + return -1; + } + + ret = mm_player_set_attribute(player->player_handle, &err_attr_name, + "profile_uri", sound_file , strlen( sound_file ) + 1, + "sound_volume_type", MM_SOUND_VOLUME_TYPE_MEDIA, + "sound_route", MM_AUDIOROUTE_PLAYBACK_NORMAL, + NULL ); + + if (MM_ERROR_NONE != ret) { + if (NULL != err_attr_name) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] Fail mm_player_set_attribute() : msg(%s), result(%x) ", err_attr_name, ret); + } + return -1; + } + + /* realize and start mm player */ + ret = mm_player_realize(player->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_realize() : %x", ret); + return -2; + } + + ret = mm_player_start(player->player_handle); + if (MM_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Player ERROR] fail mm_player_start() : %x", ret); + + mm_player_unrealize(player->player_handle); + return -3; + } + + if( NULL != sound_file ) g_free(sound_file); + if( NULL != wdata.data ) g_free(wdata.data); + + return 0; +} + + diff --git a/server/ttsd_player.h b/server/ttsd_player.h new file mode 100644 index 0000000..66af293 --- /dev/null +++ b/server/ttsd_player.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2011 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_PLAYER_H_ +#define __TTSD_PLAYER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PLAYER_END_OF_PLAYING, + PLAYER_EMPTY_SOUND_QUEUE, + PLAYER_ERROR +}player_event_e; + +typedef int (*player_result_callback_func)(player_event_e event, int uid, int utt_id); + +/* +* TTSD Player Interfaces +*/ + +int ttsd_player_init(player_result_callback_func result_cb); + +int ttsd_player_release(void); + +int ttsd_player_create_instance(const int uid); + +int ttsd_player_destroy_instance(const int uid); + +int ttsd_player_play(const int uid); + +int ttsd_player_next_play(int uid); + +int ttsd_player_stop(const int uid); + +int ttsd_player_pause(const int uid); + +int ttsd_player_resume(const int uid); + +int ttsd_player_get_current_client(); + +int ttsd_player_get_current_utterance_id(const int uid); + +int ttsd_player_all_stop(); + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_PLAYER_H_ */ diff --git a/server/ttsd_server.cpp b/server/ttsd_server.cpp new file mode 100644 index 0000000..5de3618 --- /dev/null +++ b/server/ttsd_server.cpp @@ -0,0 +1,958 @@ +/* +* Copyright (c) 2011 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 "ttsd_player.h" +#include "ttsd_data.h" +#include "ttsd_engine_agent.h" +#include "ttsd_server.h" +#include "ttsd_dbus_server.h" +#include "ttsp.h" +#include "ttsd_dbus.h" +#include "ttsd_config.h" +#include "ttsd_network.h" + + +typedef struct { + int uid; + int uttid; +} utterance_t; + +/* If current engine exist */ +static bool g_is_engine; + +/* If engine is running */ +static bool g_is_synthesizing; + +int __server_set_is_synthesizing(bool flag) +{ + g_is_synthesizing = flag; + return 0; +} + +bool __server_get_current_synthesis() +{ + return g_is_synthesizing; +} + +int __server_send_error(int uid, int utt_id, int error_code) +{ + int pid = ttsd_data_get_pid(uid); + + /* send error */ + if ( 0 != ttsdc_send_error_signal(pid, uid, utt_id, error_code)) { + ttsd_data_delete_client(uid); + } + + return 0; +} + +int __server_interrupt_client(int org_uid) +{ + int pid = ttsd_data_get_pid(org_uid); + + /* pause player */ + if (0 != ttsd_player_pause(org_uid)) { + SLOG(LOG_WARN, TAG_TTSD, "[Server ERROR] fail to ttsd_player_pause() : uid (%d)\n", org_uid); + } + + /* send message to client about changing state */ + ttsdc_send_interrupt_signal (pid, org_uid, TTSD_INTERRUPTED_PAUSED); + + /* change state */ + ttsd_data_set_client_state(org_uid, APP_STATE_PAUSED); + + return 0; +} + +int __server_start_synthesis(int uid) +{ + int result = 0; + + /* check if tts-engine is running */ + if (true == __server_get_current_synthesis()) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] TTS-engine is running \n"); + } else { + speak_data_s sdata; + if (0 == ttsd_data_get_speak_data(uid, &sdata)) { + utterance_t* utt = (utterance_t*)g_malloc0(sizeof(utterance_t)); + + if (NULL == utt) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Out of memory : utterance \n"); + return TTSD_ERROR_OUT_OF_MEMORY; + } + + utt->uid = uid; + utt->uttid = sdata.utt_id; + + SLOG(LOG_DEBUG, TAG_TTSD, "-----------------------------------------------------------"); + SLOG(LOG_DEBUG, TAG_TTSD, "ID : uid (%d), uttid(%d) ", utt->uid, utt->uttid ); + SLOG(LOG_DEBUG, TAG_TTSD, "Voice : langauge(%s), type(%d), speed(%d)", sdata.lang, sdata.vctype, sdata.speed); + SLOG(LOG_DEBUG, TAG_TTSD, "Text : %s", sdata.text); + SLOG(LOG_DEBUG, TAG_TTSD, "-----------------------------------------------------------"); + + __server_set_is_synthesizing(true); + int ret = 0; + ret = ttsd_engine_start_synthesis( sdata.lang, sdata.vctype, sdata.text, sdata.speed, (void*)utt); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] * FAIL to start SYNTHESIS !!!! * "); + + __server_set_is_synthesizing(false); + + result = TTSD_ERROR_OPERATION_FAILED; + + g_free(utt); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] SUCCESS to start synthesis"); + } + + if(sdata.text != NULL) + g_free(sdata.text); + + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] Text List is EMPTY!! "); + } + } + + return result; +} + +int __server_play_internal(int uid, app_state_e state) +{ + /* precondition */ + /* - uid is valid */ + /* - input uid is current play */ + + int ret = 0; + + if (APP_STATE_PAUSED == state) { + + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] uid(%d) is 'Pause' state : Next step is resume player and start synthesis ", uid); + + /* resume player and start speech synthesis */ + if (0 != ttsd_player_resume(uid)) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] fail to ttsd_player_resume() \n"); + } + + ret = __server_start_synthesis(uid); + + } else if(APP_STATE_READY == state) { + + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] uid(%d) is 'Ready' state : Next step is start synthesis ", uid); + + ret = __server_start_synthesis(uid); + } else { + /* NO this case */ + } + + return ret; +} + +int __server_next_synthesis(int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "===== START NEXT SYNTHESIS & PLAY"); + + /* get current playing client */ + int current_uid = ttsd_data_get_current_playing(); + + if (0 > current_uid) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] Current uid is not valid"); + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + return 0; + } + + if (true == __server_get_current_synthesis()) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] Engine has already been running. \n"); + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + return 0; + } + + /* synthesize next text */ + speak_data_s sdata; + if (0 == ttsd_data_get_speak_data(current_uid, &sdata)) { + + utterance_t* utt = (utterance_t*)g_malloc0(sizeof(utterance_t)); + + if (NULL == utt) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] fail to allocate memory : utterance \n"); + + __server_send_error(current_uid, sdata.utt_id, TTSD_ERROR_OUT_OF_MEMORY); + return TTSD_ERROR_OUT_OF_MEMORY; + } + + utt->uid = current_uid; + utt->uttid = sdata.utt_id; + + SLOG(LOG_DEBUG, TAG_TTSD, "-----------------------------------------------------------"); + SLOG(LOG_DEBUG, TAG_TTSD, "ID : uid (%d), uttid(%d) ", utt->uid, utt->uttid ); + SLOG(LOG_DEBUG, TAG_TTSD, "Voice : langauge(%s), type(%d), speed(%d)", sdata.lang, sdata.vctype, sdata.speed); + SLOG(LOG_DEBUG, TAG_TTSD, "Text : %s", sdata.text); + SLOG(LOG_DEBUG, TAG_TTSD, "-----------------------------------------------------------"); + + __server_set_is_synthesizing(true); + + int ret = 0; + ret = ttsd_engine_start_synthesis(sdata.lang, sdata.vctype, sdata.text, sdata.speed, (void*)utt); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] * FAIL to start SYNTHESIS !!!! * "); + + __server_set_is_synthesizing(false); + + __server_send_error(current_uid, sdata.utt_id, TTSD_ERROR_OPERATION_FAILED); + + g_free(utt); + } + + if(sdata.text != NULL) + g_free(sdata.text); + } + + if (0 != ttsd_player_play(current_uid)) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] __synthesis_result_callback : fail ttsd_player_play() \n"); + } else { + /* success playing */ + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] Success to start player"); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +/* +* TTS Server Callback Functions +*/ + +int __player_result_callback(player_event_e event, int uid, int utt_id) +{ + switch(event) { + case PLAYER_EMPTY_SOUND_QUEUE: + /* check whether synthesis is running */ + if (false == __server_get_current_synthesis()) { + /* check text queue is empty */ + if (0 == ttsd_data_get_speak_data_size(uid) && 0 == ttsd_data_get_sound_data_size(uid)) { + SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER Callback] all play completed \n"); + } + } + break; + + case PLAYER_ERROR: + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER Callback ERROR] callback : player error \n"); + + __server_send_error(uid, utt_id, TTSD_ERROR_OPERATION_FAILED); + break; + + case PLAYER_END_OF_PLAYING: + break; + } + + return 0; +} + +int __synthesis_result_callback(ttsp_result_event_e event, const void* data, unsigned int data_size, void *user_data) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "===== SYNTHESIS RESULT CALLBACK"); + + utterance_t* utt_get_param; + utt_get_param = (utterance_t*)user_data; + + int uid = utt_get_param->uid; + int uttid = utt_get_param->uttid; + + if (NULL == utt_get_param) { + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER ERROR] User data is NULL \n" ); + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + return -1; + } + + /* Synthesis is success */ + if (TTSP_RESULT_EVENT_START == event || TTSP_RESULT_EVENT_CONTINUE == event || TTSP_RESULT_EVENT_FINISH == event) { + + if (TTSP_RESULT_EVENT_START == event) SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER] Event : TTSP_RESULT_EVENT_START"); + if (TTSP_RESULT_EVENT_CONTINUE == event) SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER] Event : TTSP_RESULT_EVENT_CONTINUE"); + if (TTSP_RESULT_EVENT_FINISH == event) SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER] Event : TTSP_RESULT_EVENT_FINISH"); + + if (false == ttsd_data_is_uttid_valid(uid, uttid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER ERROR] uttid is NOT valid !!!! \n" ); + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; + } + + + SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER] Result Info : uid(%d), utt(%d), data(%p), data size(%d) \n", + uid, uttid, data, data_size); + + /* add wav data */ + sound_data_s temp_data; + temp_data.data = (char*)g_malloc0( sizeof(char) * data_size ); + memcpy(temp_data.data, data, data_size); + + temp_data.data_size = data_size; + temp_data.utt_id = utt_get_param->uttid; + temp_data.event = event; + + ttsp_audio_type_e audio_type; + int rate; + int channels; + + if (ttsd_engine_get_audio_format(&audio_type, &rate, &channels)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to get audio format "); + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + return -1; + } + + temp_data.audio_type = audio_type; + temp_data.rate = rate; + temp_data.channels = channels; + + if (0 != ttsd_data_add_sound_data(uid, temp_data)) { + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER ERROR] Fail to add sound data : uid(%d)\n", utt_get_param->uid); + } + + if (event == TTSP_RESULT_EVENT_FINISH) { + __server_set_is_synthesizing(false); + + if (0 != ttsd_send_start_next_synthesis(uid)) { + /* critical error */ + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER ERROR] IPC ERROR FOR NEXT SYNTHESIS \n"); + } + } + } + + else if (event == TTSP_RESULT_EVENT_CANCEL) { + SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER] Event : TTSP_RESULT_EVENT_CANCEL"); + __server_set_is_synthesizing(false); + + if (0 != ttsd_send_start_next_synthesis(uid)) { + /* critical error */ + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER ERROR] IPC ERROR FOR NEXT SYNTHESIS \n"); + } + } + + else { + SLOG(LOG_DEBUG, TAG_TTSD, "[SERVER] Event : TTSP_RESULT_EVENT_CANCEL"); + + __server_set_is_synthesizing(false); + if (0 != ttsd_send_start_next_synthesis(uid)) { + /* critical error */ + SLOG(LOG_ERROR, TAG_TTSD, "[SERVER ERROR] IPC ERROR FOR NEXT SYNTHESIS \n"); + } + } + + if (TTSP_RESULT_EVENT_FINISH == event || TTSP_RESULT_EVENT_CANCEL == event || TTSP_RESULT_EVENT_FAIL == event) { + if (NULL != utt_get_param) + free(utt_get_param); + } + + SLOG(LOG_DEBUG, TAG_TTSD, "====="); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return 0; +} + +/* +* Daemon init +*/ + +int ttsd_initialize() +{ + /* player init */ + if (ttsd_player_init(__player_result_callback)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to initialize player init \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* Engine Agent initialize */ + if (0 != ttsd_engine_agent_init(__synthesis_result_callback)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to engine agent initialize \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + /* set current engine */ + if (0 != ttsd_engine_agent_initialize_current_engine()) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] No Engine !!! \n" ); + g_is_engine = false; + } else + g_is_engine = true; + + return TTSD_ERROR_NONE; +} + + +/* +* TTS Server Functions for Client +*/ + +int ttsd_server_initialize(int pid, int uid) +{ + if (false == g_is_engine) { + if (0 != ttsd_engine_agent_initialize_current_engine()) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] No Engine !!! \n" ); + g_is_engine = false; + + return TTSD_ERROR_ENGINE_NOT_FOUND; + } else { + g_is_engine = true; + } + } + + if (-1 != ttsd_data_is_client(uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Uid has already been registered \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (0 == ttsd_data_get_client_count()) { + if (0 != ttsd_engine_agent_load_current_engine()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to load current engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + if (0 != ttsd_data_new_client(pid, uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to add client info \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (0 != ttsd_player_create_instance(uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to create player \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + return TTSD_ERROR_NONE; +} + + +int ttsd_server_finalize(int uid) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] ttsd_server_finalize : uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + ttsd_server_stop(uid); + + ttsd_player_destroy_instance(uid); + + ttsd_data_delete_client(uid); + + /* unload engine, if ref count of client is 0 */ + if (0 == ttsd_data_get_client_count()) { + if (0 != ttsd_engine_agent_unload_current_engine()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] fail to unload current engine \n"); + } else { + SLOG(LOG_DEBUG, TAG_TTSD, "[Server SUCCESS] unload current engine \n"); + } + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_add_queue(int uid, const char* text, const char* lang, int voice_type, int speed, int utt_id) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] ttsd_server_add_queue : uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* check valid voice */ + char* temp_lang = NULL; + ttsp_voice_type_e temp_type; + if (true != ttsd_engine_select_valid_voice((const char*)lang, (const ttsp_voice_type_e)voice_type, &temp_lang, &temp_type)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to select valid voice \n"); + return TTSD_ERROR_INVALID_VOICE; + } else { + if (NULL == temp_lang) + free(temp_lang); + } + + speak_data_s data; + + data.lang = strdup(lang); + data.vctype = (ttsp_voice_type_e)voice_type; + + data.speed = (ttsp_speed_e)speed; + data.utt_id = utt_id; + + data.text = strdup(text); + + /* if state is APP_STATE_READY , APP_STATE_PAUSED , only need to add speak data to queue*/ + if (0 != ttsd_data_add_speak_data(uid, data)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] ttsd_server_add_queue : Current state of uid is not 'ready' \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + if (APP_STATE_PLAYING == state) { + /* check if engine use network */ + if (ttsd_engine_agent_need_network()) { + if (false == ttsd_network_is_connected()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Disconnect network. Current engine needs network.\n"); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + if (0 != __server_start_synthesis(uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] fail to schedule synthesis : uid(%d)\n", uid); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_play(int uid) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] uid(%d) is NOT valid \n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (APP_STATE_PLAYING == state) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] Current state(%d) is 'play' \n", uid); + return TTSD_ERROR_NONE; + } + + /* check if engine use network */ + if (ttsd_engine_agent_need_network()) { + if (false == ttsd_network_is_connected()) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Disconnect network. Current engine needs network service!!!.\n"); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + int current_uid = ttsd_data_get_current_playing(); + + if (uid != current_uid && -1 != current_uid) { + /* Send interrupt message */ + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] Old uid(%d) will be interrupted into 'Pause' state \n", current_uid); + __server_interrupt_client(current_uid); + } + + /* Change current play */ + if (0 != ttsd_data_set_client_state(uid, APP_STATE_PLAYING)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Current play has already existed \n"); + return 0; + } + + if (0 != __server_play_internal(uid, state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to start synthesis : uid(%d)\n", uid); + return TTSD_ERROR_OPERATION_FAILED; + } + + return TTSD_ERROR_NONE; +} + + +int ttsd_server_stop(int uid) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) { + ttsd_data_set_client_state(uid, APP_STATE_READY); + + if (0 != ttsd_player_stop(uid)) + SLOG(LOG_WARN, TAG_TTSD, "[Server] Fail to ttsd_player_stop()\n"); + + if (true == __server_get_current_synthesis()) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] TTS-engine is running \n"); + + int ret = 0; + ret = ttsd_engine_cancel_synthesis(); + if (0 != ret) + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail to cancel synthesis : ret(%d)", ret); + + __server_set_is_synthesizing(false); + } + + /* Reset all data */ + ttsd_data_clear_data(uid); + } else { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] Current state is 'ready' \n"); + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_pause(int uid, int* utt_id) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] ttsd_server_pause : uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (APP_STATE_PLAYING != state) { + SLOG(LOG_WARN, TAG_TTSD, "[Server WARNING] Current state is not 'play' \n"); + return TTSD_ERROR_INVALID_STATE; + } + + int ret = 0; + ret = ttsd_player_pause(uid); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] fail player_pause() : ret(%d)\n", ret); + return TTSD_ERROR_OPERATION_FAILED; + } + + ttsd_data_set_client_state(uid, APP_STATE_PAUSED); + + return TTSD_ERROR_NONE; +} + +int ttsd_server_get_support_voices(int uid, GList** voice_list) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* get voice list*/ + if (0 != ttsd_engine_get_voice_list(voice_list)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] Fail ttsd_server_get_support_voices() \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Server SUCCESS] Get supported voices \n"); + + return TTSD_ERROR_NONE; +} + +int ttsd_server_get_current_voice(int uid, char** language, int* voice_type) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] ttsd_server_get_current_voice : uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* get current voice */ + int ret = ttsd_engine_get_default_voice(language, (ttsp_voice_type_e*)voice_type); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server ERROR] fail ttsd_server_get_support_voices() \n"); + return ret; + } + + SLOG(LOG_DEBUG, TAG_TTSD, "[Server] Get default language (%s), voice type(%d) \n", *language, *voice_type); + + return TTSD_ERROR_NONE; +} + + +/* +* TTS Server Functions for Setting * +*/ + +int ttsd_server_setting_initialize(int uid) +{ + if (false == g_is_engine) { + if (0 != ttsd_engine_agent_initialize_current_engine()) { + SLOG(LOG_WARN, TAG_TTSD, "[Server Setting WARNING] No Engine !!! \n" ); + g_is_engine = false; + return TTSD_ERROR_ENGINE_NOT_FOUND; + } else { + g_is_engine = true; + } + } + + if (-1 != ttsd_data_is_client(uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] pid has already been registered \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (0 == ttsd_data_get_client_count()) { + if( 0 != ttsd_engine_agent_load_current_engine() ) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] Fail to load current engine \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + } + + /* register pid */ + if (0 != ttsd_data_new_client(uid, uid)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] Fail to add client info \n"); + return TTSD_ERROR_OPERATION_FAILED; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_finalize(int uid) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid (%s)\n", uid); + return TTSD_ERROR_INVALID_PARAMETER; + } + + ttsd_data_delete_client(uid); + + /* unload engine, if ref count of client is 0 */ + if (0 == ttsd_data_get_client_count()) + { + if (0 != ttsd_engine_agent_unload_current_engine()) + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to unload current engine \n"); + else + SLOG(LOG_DEBUG, TAG_TTSD, "[Server Setting SUCCESS] unload current engine \n"); + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_get_engine_list(int uid, GList** engine_list) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int ret = 0; + ret = ttsd_engine_setting_get_engine_list(engine_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to get engine list : result(%d)\n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_get_current_engine(int uid, char** engine_id) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int ret = 0; + ret = ttsd_engine_setting_get_engine(engine_id); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] Fail to get current engine : result(%d) \n", ret); + return ret; + } + + + return TTSD_ERROR_NONE; +} + +bool __get_client_cb(int pid, int uid, app_state_e state, void* user_data) +{ + /* clear client data */ + ttsd_data_clear_data(uid); + ttsd_data_set_client_state(uid, APP_STATE_READY); + + /* send message */ + if ( 0 != ttsdc_send_interrupt_signal(pid, uid, TTSD_INTERRUPTED_STOPPED)) { + /* remove client */ + ttsd_data_delete_client(uid); + } + + return true; +} + +int ttsd_server_setting_set_current_engine(int uid, const char* engine_id) +{ + /* check if pid is valid */ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + if (true == ttsd_engine_agent_is_same_engine(engine_id)) { + SLOG(LOG_DEBUG, TAG_TTSD, "[Server Setting] new engine is the same as current engine \n"); + return TTSD_ERROR_NONE; + } + + /* stop all player */ + ttsd_player_all_stop(); + + /* send interrupt message to all clients */ + ttsd_data_foreach_clients(__get_client_cb, NULL); + + /* set engine */ + int ret = 0; + ret = ttsd_engine_setting_set_engine(engine_id); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to set current engine : result(%d) \n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_get_voice_list(int uid, char** engine_id, GList** voice_list) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* get language list from engine */ + int ret = 0; + ret = ttsd_engine_setting_get_voice_list(engine_id, voice_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] Fail to get voice list : result(%d)\n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_get_default_voice(int uid, char** language, ttsp_voice_type_e* vctype) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int ret = 0; + ret = ttsd_engine_setting_get_default_voice(language, vctype); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] Fail to get default voice : result(%d) \n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_set_default_voice(int uid, const char* language, int vctype) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* set current language */ + int ret = 0; + ret = ttsd_engine_setting_set_default_voice((const char*)language, (const ttsp_voice_type_e)vctype); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to set default voice : result(%d) \n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_get_engine_setting(int uid, char** engine_id, GList** engine_setting_list) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int ret = 0; + ret = ttsd_engine_setting_get_engine_setting_info(engine_id, engine_setting_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to get engine setting info : result(%d)\n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_set_engine_setting(int uid, const char* key, const char* value) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + int ret = 0; + ret = ttsd_engine_setting_set_engine_setting(key, value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to set engine setting info : result(%d)\n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_get_default_speed(int uid, int* default_speed) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* get current speed */ + int ret = 0; + ret = ttsd_engine_setting_get_default_speed((ttsp_speed_e*)default_speed); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to get default speed : result(%d)\n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +int ttsd_server_setting_set_default_speed(int uid, int default_speed) +{ + app_state_e state; + if (0 > ttsd_data_get_client_state(uid, &state)) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] uid is not valid \n"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + /* set default speed */ + int ret = 0; + ret = ttsd_engine_setting_set_default_speed((ttsp_speed_e)default_speed); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSD, "[Server Setting ERROR] fail to set default speed : result(%d)\n", ret); + return ret; + } + + return TTSD_ERROR_NONE; +} + +/* +* Server API for Internal event +*/ + +int ttsd_server_start_next_play(int uid) +{ + SLOG(LOG_DEBUG, TAG_TTSD, "===== NEXT PLAY START"); + + int ret = ttsd_player_next_play(uid); + + SLOG(LOG_DEBUG, TAG_TTSD, "===== "); + SLOG(LOG_DEBUG, TAG_TTSD, " "); + + return ret ; +} + +int ttsd_server_start_next_synthesis(int uid) +{ + return __server_next_synthesis(uid); +} + + diff --git a/server/ttsd_server.h b/server/ttsd_server.h new file mode 100644 index 0000000..7e1f40f --- /dev/null +++ b/server/ttsd_server.h @@ -0,0 +1,92 @@ +/* +* Copyright (c) 2011 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_SERVER_CORE_H_ +#define __TTSD_SERVER_CORE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* Daemon init +*/ + +/** Daemon initialize */ +int ttsd_initialize(); + +/* +* Server API for client +*/ + +int ttsd_server_initialize(int pid, int uid); + +int ttsd_server_finalize(int uid); + +int ttsd_server_get_support_voices(int uid, GList** voice_list); + +int ttsd_server_get_current_voice(int uid, char** language, int* voice_type); + +int ttsd_server_add_queue(int uid, const char* text, const char* lang, int voice_type, int speed, int utt_id); + +int ttsd_server_play(int uid); + +int ttsd_server_stop(int uid); + +int ttsd_server_pause(int uid, int* utt_id); + +/* +* Server API for Internal event +*/ + +int ttsd_server_start_next_play(int uid); + +int ttsd_server_start_next_synthesis(int uid); + +/* +* Server API for setting +*/ + +int ttsd_server_setting_initialize(int uid); + +int ttsd_server_setting_finalize(int uid); + +int ttsd_server_setting_get_engine_list(int uid, GList** engine_list); + +int ttsd_server_setting_get_current_engine(int uid, char** engine_id); + +int ttsd_server_setting_set_current_engine(int uid, const char* engine_id); + +int ttsd_server_setting_get_voice_list(int uid, char** engine_id, GList** voice_list); + +int ttsd_server_setting_get_default_voice(int uid, char** language, ttsp_voice_type_e* vctype); + +int ttsd_server_setting_set_default_voice(int uid, const char* language, int vctype); + +int ttsd_server_setting_get_default_speed(int uid, int* default_speed); + +int ttsd_server_setting_set_default_speed(int uid, int default_speed); + +int ttsd_server_setting_get_engine_setting(int uid, char** engine_id, GList** engine_setting_list); + +int ttsd_server_setting_set_engine_setting(int uid, const char* key, const char* value); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TTSD_SERVER_CORE_H_ */ diff --git a/server/ttsp.h b/server/ttsp.h new file mode 100644 index 0000000..4a49a26 --- /dev/null +++ b/server/ttsp.h @@ -0,0 +1,379 @@ +/* +* Copyright (c) 2011 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 __TTSP_H__ +#define __TTSP_H__ + +#include +#include + +/** +* @addtogroup TTS_ENGINE_MODULE +* @{ +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief Enumerations of error codes. +*/ +typedef enum { + TTSP_ERROR_NONE = 0, /**< Successful */ + TTSP_ERROR_OUT_OF_MEMORY = -ENOMEM, /**< Out of Memory */ + TTSP_ERROR_IO_ERROR = -EIO, /**< I/O error */ + TTSP_ERROR_INVALID_PARAMETER = -EINVAL, /**< Invalid parameter */ + TTSP_ERROR_OUT_OF_NETWORK = -ENETDOWN, /**< Out of network */ + TTSP_ERROR_INVALID_STATE = -0x0100021, /**< Invalid state */ + TTSP_ERROR_INVALID_VOICE = -0x0100022, /**< Invalid voice */ + TTSP_ERROR_OPERATION_FAILED = -0x0100025 /**< Operation failed */ +}ttsp_error_e; + +/** +* @brief Enumerations of speaking speed. +*/ +typedef enum { + TTSP_SPEED_VERY_SLOW = 1, /**< Very slow */ + TTSP_SPEED_SLOW, /**< Slow */ + TTSP_SPEED_NORMAL, /**< Normal */ + TTSP_SPEED_FAST, /**< Fast */ + TTSP_SPEED_VERY_FAST /**< Very fast */ +}ttsp_speed_e; + +/** +* @brief Enumerations of voice type. +*/ +typedef enum { + TTSP_VOICE_TYPE_MALE = 1, /**< Male */ + TTSP_VOICE_TYPE_FEMALE, /**< Female */ + TTSP_VOICE_TYPE_CHILD, /**< Child */ + TTSP_VOICE_TYPE_USER1, /**< Engine defined */ + TTSP_VOICE_TYPE_USER2, /**< Engine defined */ + TTSP_VOICE_TYPE_USER3 /**< Engine defined */ +}ttsp_voice_type_e; + +/** +* @brief Enumerations of audio type. +*/ +typedef enum { + TTSP_AUDIO_TYPE_RAW = 0, /**< PCM audio type */ + TTSP_AUDIO_TYPE_WAV, /**< Wave audio type */ + TTSP_AUDIO_TYPE_MP3, /**< MP3 audio type */ + TTSP_AUDIO_TYPE_AMR /**< AMR audio type */ +}ttsp_audio_type_e; + +/** +* @brief Enumerations of result event type. +*/ +typedef enum { + TTSP_RESULT_EVENT_FAIL = -1, /**< event when the voice synthesis is failed */ + TTSP_RESULT_EVENT_START = 1, /**< event when the sound data is first data by callback function */ + TTSP_RESULT_EVENT_CONTINUE = 2, /**< event when the next sound data exist, not first and not last */ + TTSP_RESULT_EVENT_FINISH = 3, /**< event when the sound data is last data or sound data is only one result */ + TTSP_RESULT_EVENT_CANCEL = 4, /**< event when the voice synthesis has been canceled */ +}ttsp_result_event_e; + +/** +* @brief Called when the daemon gets synthesized result. +* +* @param[in] event A result event +* @param[in] data Result data +* @param[in] data_size Result data size +* @param[in] user_data The user data passed from the start synthesis function +* +* @return @c true to continue with the next iteration of synthesis \n @c false to stop +* +* @pre ttspe_start_synthesis() will invoke this callback. +* +* @see ttspe_start_synthesis() +*/ +typedef bool (*ttspe_result_cb)(ttsp_result_event_e event, const void* data, unsigned int data_size, void *user_data); + +/** +* @brief Called when the daemon gets a language and a voice type. +* +* @param[in] language A language is specified as an ISO 3166 alpha-2 two letter country-code +* followed by ISO 639-1 for the two-letter language code. \n +* For example, "ko_KR" for Korean, "en_US" for American English. +* @param[in] type A voice type +* @param[in] user_data The user data passed from the the foreach function +* +* @return @c true to continue with the next iteration of the loop \n @c false to break out of the loop +* +* @pre ttspe_foreach_supported_voices() will invoke this callback. +* +* @see ttspe_foreach_supported_voices() +*/ +typedef bool (*ttspe_supported_voice_cb)(const char* language, ttsp_voice_type_e type, void* user_data); + +/** +* @brief Called when the daemon gets a engine setting. +* +* @param[in] key A key +* @param[in] value A value +* @param[in] user_data The user data passed from the foreach function +* +* @return @c true to continue with the next iteration of the loop \n @c false to break out of the loop +* +* @pre ttspe_foreach_engine_settings() will invoke this callback. +* +* @see ttspe_foreach_engine_settings() +*/ +typedef bool (*ttspe_engine_setting_cb)(const char* key, const char* value, void* user_data); + +/** +* @brief Initializes the engine. +* +* @param[in] callbacks A callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_INVALID_STATE Already initialized +* @retval #TTSP_ERROR_OPERATION_FAILED Operation failed +* +* @see ttspe_deinitialize() +*/ +typedef int (* ttspe_initialize)(ttspe_result_cb callback); + +/** +* @brief Deinitializes the engine. +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_STATE Not initialized +* +* @see ttspe_initialize() +*/ +typedef int (* ttspe_deinitialize)(void); + +/** +* @brief Retrieves all supported voices of the engine using callback function. +* +* @param[in] callback A callback function +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_INVALID_STATE Not initialized +* +* @post This function invokes ttspe_supported_voice_cb() repeatedly for getting all supported languages. +* +* @see ttspe_supported_voice_cb() +*/ +typedef int (* ttspe_foreach_supported_voices)(ttspe_supported_voice_cb callback, void* user_data); + +/** +* @brief Checks whether the voice is valid or not. +* +* @param[in] language A language +* @param[in] type A voice type +* +* @return @c true to be valid \n @c false not to be valid +* +* @see ttspe_foreach_supported_voices() +*/ +typedef bool (* ttspe_is_valid_voice)(const char* language, ttsp_voice_type_e type); + +/** +* @brief Gets audio format of the engine. +* +* @param[out] types A audio type +* @param[out] rate A sample rate +* @param[out] channels Channels +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_INVALID_STATE Not initialized +*/ +typedef int (* ttspe_get_audio_format)(ttsp_audio_type_e* audio_type, int* rate, int* channel); + +/** +* @brief Starts voice synthesis, asynchronously. +* +* @param[in] language A language +* @param[in] type A voice type +* @param[in] text Texts +* @param[in] speed A speaking speed +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_INVALID_STATE Not initialized or already started synthesis +* @retval #TTSP_ERROR_INVALID_VOICE Invalid voice +* @retval #TTSP_ERROR_OPERATION_FAILED Operation failed +* @retval #TTSP_ERROR_OUT_OF_NETWORK Out of network +* +* @post This function invokes ttspe_result_cb(). +* +* @see ttspe_result_cb() +* @see ttspe_cancel_synthesis() +*/ +typedef int (* ttspe_start_synthesis)(const char* language, ttsp_voice_type_e type, const char* text, ttsp_speed_e speed, void* user_data); + +/** +* @brief Cancels voice synthesis. +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_STATE Not initialized or not started synthesis +* +* @pre The ttspe_start_synthesis() should be performed +* +* @see ttspe_start_synthesis() +*/ +typedef int (* ttspe_cancel_synthesis)(void); + +/** +* @brief Gets setting information of the engine. +* +* @param[in] callback A callback function. +* @param[in] user_data The user data to be passed to the callback function. +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_INVALID_STATE Not initialized +* @retval #TTSP_ERROR_OPERATION_FAILED Operation failed +* +* @post This function invokes ttspe_engine_setting_cb() repeatedly for getting all engine settings. +* +* @see ttspe_engine_setting_cb() +*/ +typedef int (* ttspe_foreach_engine_settings)(ttspe_engine_setting_cb callback, void* user_data); + +/** +* @brief Sets setting information of the engine. +* +* @param[in] key A key. +* @param[in] value A value. +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_INVALID_STATE Not initialized +* @retval #TTSP_ERROR_OPERATION_FAILED Operation failed +* +* @see ttspe_foreach_engine_settings() +*/ +typedef int (* ttspe_set_engine_setting)(const char* key, const char* value); + +/** +* @brief A structure of the engine functions +*/ +typedef struct { + int size; /**< Size of structure */ + int version; /**< Version */ + + ttspe_initialize initialize; /**< Initialize engine */ + ttspe_deinitialize deinitialize; /**< Shutdown engine */ + + /* Get / Set engine information */ + ttspe_foreach_supported_voices foreach_voices; /**< Get voice list */ + ttspe_is_valid_voice is_valid_voice; /**< Check voice */ + ttspe_get_audio_format get_audio_format; /**< Get audio format function */ + + /* Control synthesis */ + ttspe_start_synthesis start_synth; /**< Start synthesis */ + ttspe_cancel_synthesis cancel_synth; /**< Cancel synthesis */ + + /* Engine setting */ + ttspe_foreach_engine_settings foreach_engine_setting; /**< Foreach engine setting */ + ttspe_set_engine_setting set_engine_setting; /**< Set engine setting */ +} ttspe_funcs_s; + +/** +* @brief A structure of the daemon functions +*/ +typedef struct { + int size; /**< size */ + int version; /**< version */ + +}ttspd_funcs_s; + +/** +* @brief Loads the engine by the daemon. +* +* @param[in] pdfuncs The daemon functions +* @param[out] pefuncs The engine functions +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_OPERATION_FAILED Operation failed +* +* @pre The ttsp_get_engine_info() should be successful. +* @post The daemon calls the engine functions of ttspe_funcs_s. +* +* @see ttsp_get_engine_info() +* @see ttsp_unload_engine() +*/ +int ttsp_load_engine(ttspd_funcs_s* pdfuncs, ttspe_funcs_s* pefuncs); + +/** +* @brief Unloads the engine by the daemon. +* +* @pre The ttsp_load_engine() should be performed. +* +* @see ttsp_load_engine() +*/ +void ttsp_unload_engine(void); + +/** +* @brief Called to get this engine base information. +* +* @param[in] engine_uuid The engine id +* @param[in] engine_name The engine name +* @param[in] setting_ug_name The setting ug name +* @param[in] use_network @c true to need network \n @c false not to need network +* @param[in] user_data The user data passed from the engine info function +* +* @pre ttsp_get_engine_info() will invoke this callback. +* +* @see ttsp_get_engine_info() +*/ +typedef void (*ttsp_engine_info_cb)(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, + bool use_network, void* user_data); + +/** +* @brief Gets base information of the engine by the daemon. +* +* @param[in] callback A callback function +* @param[in] user_data The user data to be passed to the callback function +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #TTSP_ERROR_OPERATION_FAILED Operation failed +* +* @post This function invokes ttsp_engine_info_cb() for getting engine information. +* +* @see ttsp_engine_info_cb() +* @see ttsp_load_engine() +*/ +int ttsp_get_engine_info(ttsp_engine_info_cb callback, void* user_data); + +#ifdef __cplusplus +} +#endif + +/** +* @}@} +*/ + +#endif /* __TTSP_H__ */ -- 2.7.4