2 * Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
19 #include "ttsd_main.h"
20 #include "ttsd_engine_agent.h"
21 #include "ttsd_config.h"
23 #define ENGINE_PATH_SIZE 256
26 * Internal data structure
28 typedef struct _ttsengine_info {
33 char* engine_setting_path;
35 /* info for using engine load */
39 tts_engine_callback_s* callbacks;
41 /* engine base setting */
59 static bool g_agent_init;
61 /** Current engine information */
62 static ttsengine_info_s* g_engine_info = NULL;
64 /** Current voice information */
65 static GSList* g_cur_voices = NULL;
67 /** Callback function for voice list */
68 static bool __supported_voice_cb(const char* language, int type, void* user_data);
70 /** Free voice list */
71 static void __free_voice_list(GList* voice_list);
73 static int ttsd_print_voicelist();
75 /** Get engine info */
76 int __internal_get_engine_info(ttse_request_callback_s* callback);
78 static const char* __ttsd_get_engine_error_code(ttse_error_e err)
81 case TTSE_ERROR_NONE: return "TTSE_ERROR_NONE";
82 case TTSE_ERROR_OUT_OF_MEMORY: return "TTSE_ERROR_OUT_OF_MEMORY";
83 case TTSE_ERROR_IO_ERROR: return "TTSE_ERROR_IO_ERROR";
84 case TTSE_ERROR_INVALID_PARAMETER: return "TTSE_ERROR_INVALID_PARAMETER";
85 case TTSE_ERROR_NETWORK_DOWN: return "TTSE_ERROR_NETWORK_DOWN";
86 case TTSE_ERROR_INVALID_STATE: return "TTSE_ERROR_INVALID_STATE";
87 case TTSE_ERROR_INVALID_VOICE: return "TTSE_ERROR_INVALID_VOICE";
88 case TTSE_ERROR_OPERATION_FAILED: return "TTSE_ERROR_OPERATION_FAILED";
90 return "Invalid error code";
94 int ttsd_engine_agent_init()
96 if (true == g_agent_init) {
97 SLOG(LOG_WARN, tts_tag(), "[Engine Agent] Already initialized");
98 return TTSD_ERROR_OPERATION_FAILED;
101 ttsengine_info_s* temp;
102 temp = (ttsengine_info_s*)calloc(1, sizeof(ttsengine_info_s));
104 SLOG(LOG_WARN, tts_tag(), "[Engine Agent] Fail to alloc memory");
105 return TTSD_ERROR_OUT_OF_MEMORY;
108 if (0 != ttsd_config_get_default_voice(&(temp->default_lang), &(temp->default_vctype))) {
109 SLOG(LOG_WARN, tts_tag(), "[Server WARNING] There is No default voice in config");
110 /* Set default voice */
111 temp->default_lang = strdup(TTS_BASE_LANGUAGE);
112 temp->default_vctype = TTSE_VOICE_TYPE_FEMALE;
115 SLOG(LOG_DEBUG, tts_tag(), "[Server DEBUG] language(%s), type(%d)", temp->default_lang, temp->default_vctype);
117 if (0 != ttsd_config_get_default_speed(&(temp->default_speed))) {
118 SLOG(LOG_WARN, tts_tag(), "[Server WARNING] There is No default speed in config");
119 temp->default_speed = TTS_SPEED_NORMAL;
122 if (0 != ttsd_config_get_default_pitch(&(temp->default_pitch))) {
123 SLOG(LOG_WARN, tts_tag(), "[Server WARNING] There is No default pitch in config");
124 temp->default_pitch = TTS_PITCH_NORMAL;
127 temp->is_loaded = false;
128 g_engine_info = temp;
132 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Initialize Engine Agent");
136 int ttsd_engine_agent_release()
138 if (false == g_agent_init) {
139 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
140 return TTSD_ERROR_OPERATION_FAILED;
143 /* unload current engine */
144 if (g_engine_info->is_loaded) {
145 ttsd_engine_agent_unload_current_engine();
148 if (NULL != g_engine_info->default_lang) {
149 free(g_engine_info->default_lang);
150 g_engine_info->default_lang = NULL;
153 if (NULL != g_engine_info->engine_uuid) {
154 free(g_engine_info->engine_uuid);
155 g_engine_info->engine_uuid = NULL;
158 if (NULL != g_engine_info->engine_name) {
159 free(g_engine_info->engine_name);
160 g_engine_info->engine_name = NULL;
163 if (NULL != g_engine_info->engine_setting_path) {
164 free(g_engine_info->engine_setting_path);
165 g_engine_info->engine_setting_path = NULL;
168 if (NULL != g_engine_info->engine_path) {
169 free(g_engine_info->engine_path);
170 g_engine_info->engine_path = NULL;
174 g_engine_info = NULL;
176 g_agent_init = false;
178 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Release Engine Agent");
183 static bool __set_voice_info_cb(const char* language, int type, void* user_data)
185 if (NULL == language) {
186 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
190 ttsvoice_s* voice = calloc(1, sizeof(ttsvoice_s));
192 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
195 voice->lang = strdup(language);
198 voice->client_ref_count = 0;
199 voice->is_loaded = false;
201 if (0 == strcmp(g_engine_info->default_lang, language) && g_engine_info->default_vctype == type) {
202 voice->is_default = true;
203 voice->is_loaded = true;
205 voice->is_default = false;
208 g_cur_voices = g_slist_append(g_cur_voices, voice);
213 static int __update_voice_list()
215 if (false == g_agent_init) {
216 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
217 return TTSD_ERROR_OPERATION_FAILED;
221 if (NULL != g_cur_voices) {
223 ttsvoice_s* data = NULL;
225 iter = g_slist_nth(g_cur_voices, 0);
226 while (NULL != iter) {
230 if (NULL != data->lang) {
235 g_cur_voices = g_slist_remove(g_cur_voices, data);
240 iter = g_slist_nth(g_cur_voices, 0);
247 ret = g_engine_info->callbacks->foreach_voices(__set_voice_info_cb, NULL);
249 if (0 != ret || 0 >= g_slist_length(g_cur_voices)) {
250 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
254 #ifdef ENGINE_AGENT_DEBUG
255 ttsd_print_voicelist();
260 int ttsd_engine_agent_load_current_engine(ttse_request_callback_s* callback)
262 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent DEBUG] load current engine START");
265 if (false == g_agent_init) {
266 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
267 return TTSD_ERROR_OPERATION_FAILED;
270 /* check whether current engine is loaded or not */
271 if (true == g_engine_info->is_loaded) {
272 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent] Engine has already been loaded ");
276 if (NULL == callback) {
277 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
278 return TTSD_ERROR_ENGINE_NOT_FOUND;
281 if (NULL == callback->get_info
282 || NULL == callback->initialize || NULL == callback->deinitialize
283 || NULL == callback->foreach_voices || NULL == callback->is_valid_voice
284 || NULL == callback->set_pitch
285 || NULL == callback->load_voice || NULL == callback->unload_voice
286 || NULL == callback->start_synth || NULL == callback->cancel_synth
287 || NULL == callback->check_app_agreed || NULL == callback->need_app_credential) {
288 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
289 return TTSD_ERROR_ENGINE_NOT_FOUND;
292 /* Get current engine info */
293 int ret = __internal_get_engine_info(callback);
295 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get engine info");
299 /* Initialize engine */
300 ret = g_engine_info->callbacks->initialize();
302 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to initialize current engine : %s", __ttsd_get_engine_error_code(ret));
303 return TTSD_ERROR_OPERATION_FAILED;
306 /* Get voice info of current engine */
307 ret = __update_voice_list();
309 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set voice info : result(%d)", ret);
310 return TTSD_ERROR_OPERATION_FAILED;
313 /* Select default voice */
314 if (NULL != g_engine_info->default_lang) {
315 bool is_valid = false;
316 ret = g_engine_info->callbacks->is_valid_voice(g_engine_info->default_lang, g_engine_info->default_vctype, &is_valid);
318 if (true == is_valid) {
319 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set origin default voice to current engine : lang(%s), type(%d)",
320 g_engine_info->default_lang, g_engine_info->default_vctype);
322 SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Fail to set origin default voice : lang(%s), type(%d)",
323 g_engine_info->default_lang, g_engine_info->default_vctype);
325 /* TODO - Error Tolerance when Default voice is not valid */
326 return TTSD_ERROR_OPERATION_FAILED;
329 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail(Engine ERROR) : %s", __ttsd_get_engine_error_code(ret));
334 /* load default voice */
335 ret = g_engine_info->callbacks->load_voice(g_engine_info->default_lang, g_engine_info->default_vctype);
337 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Load default voice : lang(%s), type(%d)",
338 g_engine_info->default_lang, g_engine_info->default_vctype);
340 SLOG(LOG_WARN, tts_tag(), "[Engine Agent ERROR] Fail to load default voice : lang(%s), type(%d) result(%s)",
341 g_engine_info->default_lang, g_engine_info->default_vctype, __ttsd_get_engine_error_code(ret));
343 return TTSD_ERROR_OPERATION_FAILED;
346 /* set default pitch */
347 ret = g_engine_info->callbacks->set_pitch(g_engine_info->default_pitch);
349 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)",
350 g_engine_info->default_pitch, __ttsd_get_engine_error_code(ret));
353 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set default pitch : pitch(%d)", g_engine_info->default_pitch);
356 g_engine_info->is_loaded = true;
361 int ttsd_engine_agent_unload_current_engine()
363 if (false == g_agent_init) {
364 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
365 return TTSD_ERROR_OPERATION_FAILED;
368 if (false == g_engine_info->is_loaded) {
369 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Engine has already been unloaded ");
373 /* shutdown engine */
375 ret = g_engine_info->callbacks->deinitialize();
377 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent] Fail deinitialize() : %s", __ttsd_get_engine_error_code(ret));
380 /* reset current engine data */
381 g_engine_info->is_loaded = false;
384 ttsvoice_s* data = NULL;
386 iter = g_slist_nth(g_cur_voices, 0);
387 while (NULL != iter) {
391 if (NULL != data->lang) {
395 g_cur_voices = g_slist_remove(g_cur_voices, data);
400 iter = g_slist_nth(g_cur_voices, 0);
403 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent Success] Unload current engine");
408 bool ttsd_engine_agent_need_network()
410 if (false == g_agent_init) {
411 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
412 return TTSD_ERROR_OPERATION_FAILED;
415 return g_engine_info->use_network;
418 bool ttsd_engine_agent_is_same_engine(const char* engine_id)
420 if (false == g_agent_init) {
421 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
425 if (NULL == engine_id) {
426 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] engine_id is NULL");
430 if (NULL == g_engine_info) {
431 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
435 if (false == g_engine_info->is_loaded) {
436 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
440 /* compare current engine and engine id.*/
441 if (NULL != g_engine_info->engine_uuid && 0 == strncmp(g_engine_info->engine_uuid, engine_id, strlen(engine_id))) {
448 bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, int* out_type)
450 if (NULL == lang || NULL == out_lang || NULL == out_type) {
454 if (NULL == g_engine_info) {
455 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
459 if (false == g_engine_info->is_loaded) {
460 SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Not loaded engine");
464 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Select voice : input lang(%s), input type(%d), default lang(%s), default type(%d)",
465 (NULL == lang) ? "NULL" : lang, type, (NULL == g_engine_info->default_lang) ? "NULL" : g_engine_info->default_lang, g_engine_info->default_vctype);
467 /* case 1 : Both are default */
468 if (0 == strncmp(lang, "default", strlen(lang)) && 0 == type) {
469 if (NULL != g_engine_info->default_lang) {
470 *out_lang = strdup(g_engine_info->default_lang);
475 *out_type = g_engine_info->default_vctype;
480 GList* voice_list = NULL;
482 ret = g_engine_info->callbacks->foreach_voices(__supported_voice_cb, &voice_list);
483 if (0 != ret || 0 >= g_list_length(voice_list)) {
484 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
494 /* case 2 : lang and type are not default type */
495 if (0 != strncmp(lang, "default", strlen("default")) && 0 != type) {
496 iter = g_list_first(voice_list);
498 while (NULL != iter) {
499 /* Get handle data from list */
502 if (0 == strncmp(voice->language, lang, strlen(lang)) && voice->type == type) {
503 *out_lang = strdup(voice->language);
504 *out_type = voice->type;
509 iter = g_list_next(iter);
512 } else if (0 != strncmp(lang, "default", strlen("default")) && 0 == type) {
513 /* Only type is default */
514 if (0 == strncmp(lang, g_engine_info->default_lang, strlen(g_engine_info->default_lang))) {
515 *out_lang = strdup(g_engine_info->default_lang);
516 *out_type = g_engine_info->default_vctype;
519 voice_s* voice_selected = NULL;
520 iter = g_list_first(voice_list);
521 while (NULL != iter) {
522 /* Get handle data from list */
525 if (0 == strncmp(voice->language, lang, strlen(lang))) {
526 voice_selected = voice;
527 if (voice->type == g_engine_info->default_vctype) {
528 voice_selected = voice;
532 iter = g_list_next(iter);
535 if (NULL != voice_selected) {
536 *out_lang = strdup(voice_selected->language);
537 *out_type = voice_selected->type;
541 } else if (0 == strncmp(lang, "default", strlen("default")) && 0 != type) {
542 /* Only lang is default */
543 if (type == g_engine_info->default_vctype) {
544 *out_lang = strdup(g_engine_info->default_lang);
545 *out_type = g_engine_info->default_vctype;
548 voice_s* voice_selected = NULL;
549 iter = g_list_first(voice_list);
550 while (NULL != iter) {
551 /* Get handle data from list */
554 if (0 == strncmp(voice->language, g_engine_info->default_lang, strlen(g_engine_info->default_lang))) {
555 voice_selected = voice;
556 if (voice->type == type) {
557 voice_selected = voice;
561 iter = g_list_next(iter);
564 if (NULL != voice_selected) {
565 *out_lang = strdup(voice->language);
566 *out_type = voice_selected->type;
572 if (true == result) {
573 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Selected voice : lang(%s), type(%d)", *out_lang, *out_type);
576 __free_voice_list(voice_list);
583 int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
585 if (NULL == language) {
586 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] language is NULL");
590 if (false == g_agent_init) {
591 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
592 return TTSD_ERROR_OPERATION_FAILED;
595 if (NULL == g_engine_info) {
596 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
600 if (false == g_engine_info->is_loaded) {
601 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
602 return TTSD_ERROR_ENGINE_NOT_FOUND;
606 bool is_valid = false;
607 ret = g_engine_info->callbacks->is_valid_voice(language, vctype, &is_valid);
609 if (true == is_valid) {
610 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Current voice is valid : lang(%s), type(%d)",
611 (NULL == g_engine_info->default_lang) ? "NULL" : g_engine_info->default_lang, g_engine_info->default_vctype);
613 SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Current voice is invalid : lang(%s), type(%d)",
614 (NULL == g_engine_info->default_lang) ? "NULL" : g_engine_info->default_lang, g_engine_info->default_vctype);
616 return TTSD_ERROR_OPERATION_FAILED;
619 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail(Engine ERROR) : %s", __ttsd_get_engine_error_code(ret));
625 ttsvoice_s* data = NULL;
627 /* Update new default voice info */
628 iter = g_slist_nth(g_cur_voices, 0);
629 while (NULL != iter) {
630 /* Get handle data from list */
634 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Voice data is NULL");
635 return TTSD_ERROR_OPERATION_FAILED;
638 if (NULL != data->lang) {
639 if (0 == strcmp(data->lang, language) && data->type == vctype) {
640 data->is_default = true;
641 if (0 == data->client_ref_count) {
643 ret = g_engine_info->callbacks->load_voice(data->lang, data->type);
645 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] load voice : lang(%s), type(%d)",
646 data->lang, data->type);
647 data->is_loaded = true;
649 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
650 data->lang, data->type, __ttsd_get_engine_error_code(ret));
658 iter = g_slist_next(iter);
661 #ifdef ENGINE_AGENT_DEBUG
662 ttsd_print_voicelist();
665 /* Update old default voice info */
666 iter = g_slist_nth(g_cur_voices, 0);
667 while (NULL != iter) {
668 /*Get handle data from list*/
672 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Voice data is NULL");
673 return TTSD_ERROR_OPERATION_FAILED;
676 if (0 == strcmp(data->lang, g_engine_info->default_lang) && data->type == g_engine_info->default_vctype) {
677 data->is_default = false;
678 if (0 == data->client_ref_count) {
680 ret = g_engine_info->callbacks->unload_voice(data->lang, data->type);
682 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)",
683 data->lang, data->type);
684 data->is_loaded = false;
686 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
687 data->lang, data->type, __ttsd_get_engine_error_code(ret));
694 iter = g_slist_next(iter);
697 if (NULL != g_engine_info->default_lang) {
698 free(g_engine_info->default_lang);
699 g_engine_info->default_lang = NULL;
702 g_engine_info->default_lang = strdup(language);
703 g_engine_info->default_vctype = vctype;
705 #ifdef ENGINE_AGENT_DEBUG
706 ttsd_print_voicelist();
709 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set default voice : lang(%s), type(%d)",
710 g_engine_info->default_lang, g_engine_info->default_vctype);
715 int ttsd_engine_agent_set_default_speed(int speed)
717 if (false == g_agent_init) {
718 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
719 return TTSD_ERROR_OPERATION_FAILED;
722 g_engine_info->default_speed = speed;
727 int ttsd_engine_agent_set_default_pitch(int pitch)
729 if (false == g_agent_init) {
730 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
731 return TTSD_ERROR_OPERATION_FAILED;
734 if (NULL == g_engine_info) {
735 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No engine info");
736 return TTSD_ERROR_ENGINE_NOT_FOUND;
739 if (false == g_engine_info->is_loaded) {
740 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
741 return TTSD_ERROR_ENGINE_NOT_FOUND;
744 int ret = g_engine_info->callbacks->set_pitch(pitch);
746 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)",
747 pitch, __ttsd_get_engine_error_code(ret));
748 return TTSD_ERROR_OPERATION_FAILED;
751 g_engine_info->default_pitch = pitch;
753 SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Set pitch(%d)", pitch);
757 int ttsd_engine_agent_is_credential_needed(int uid, bool* credential_needed)
759 if (NULL == credential_needed) {
760 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid Parameter");
761 return TTSD_ERROR_INVALID_PARAMETER;
764 if (false == g_agent_init) {
765 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
766 return TTSD_ERROR_OPERATION_FAILED;
769 if (false == g_engine_info->is_loaded) {
770 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
771 return TTSD_ERROR_OPERATION_FAILED;
774 if (NULL == g_engine_info->callbacks->need_app_credential) {
775 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not support to check app credential");
776 return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
780 result = g_engine_info->callbacks->need_app_credential();
781 *credential_needed = result;
783 SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Need app credential, credential_needed(%d)", *credential_needed);
784 return TTSD_ERROR_NONE;
787 /******************************************************************************************
788 * TTS Engine Interfaces for client
789 *******************************************************************************************/
791 int ttsd_engine_load_voice(const char* lang, const int vctype)
793 if (false == g_agent_init) {
794 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
795 return TTSD_ERROR_OPERATION_FAILED;
798 if (false == g_engine_info->is_loaded) {
799 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
800 return TTSD_ERROR_ENGINE_NOT_FOUND;
804 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No language parameter");
805 return TTSD_ERROR_INVALID_PARAMETER;
808 /* 1. Find voice info */
811 ttsvoice_s* data = NULL;
813 iter = g_slist_nth(g_cur_voices, 0);
814 while (NULL != iter) {
815 /*Get handle data from list*/
819 if (NULL != data->lang && 0 == strcmp(data->lang, lang) && data->type == vctype) {
820 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
821 data->is_default, data->is_loaded, data->client_ref_count, data->lang, data->type);
827 iter = g_slist_next(iter);
832 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
833 return TTSD_ERROR_OPERATION_FAILED;
836 /* 2. increse ref count */
837 data->client_ref_count++;
839 /* 3. if ref count change 0 to 1 and not default, load voice */
840 if (1 == data->client_ref_count && false == data->is_default) {
842 ret = g_engine_info->callbacks->load_voice(data->lang, data->type);
844 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Load voice : lang(%s), type(%d)",
845 data->lang, data->type);
846 data->is_loaded = true;
848 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
849 data->lang, data->type, __ttsd_get_engine_error_code(ret));
851 return TTSD_ERROR_OPERATION_FAILED;
854 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Not load voice : default voice(%d) or ref count(%d)",
855 data->is_default, data->client_ref_count);
858 #ifdef ENGINE_AGENT_DEBUG
859 ttsd_print_voicelist();
865 int ttsd_engine_unload_voice(const char* lang, const int vctype)
867 if (false == g_agent_init) {
868 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
869 return TTSD_ERROR_OPERATION_FAILED;
872 if (false == g_engine_info->is_loaded) {
873 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
874 return TTSD_ERROR_ENGINE_NOT_FOUND;
878 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No language parameter");
879 return TTSD_ERROR_INVALID_PARAMETER;
882 /* 1. Find voice info */
885 ttsvoice_s* data = NULL;
887 iter = g_slist_nth(g_cur_voices, 0);
888 while (NULL != iter) {
889 /*Get handle data from list*/
893 if (NULL != data->lang && 0 == strcmp(data->lang, lang) && data->type == vctype) {
894 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
895 data->is_default, data->is_loaded, data->client_ref_count, data->lang, data->type);
901 iter = g_slist_next(iter);
906 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
907 return TTSD_ERROR_OPERATION_FAILED;
910 /* 2. Decrese ref count */
911 data->client_ref_count--;
913 /* 3. if ref count change 0 and not default, load voice */
914 if (0 == data->client_ref_count && false == data->is_default) {
916 ret = g_engine_info->callbacks->unload_voice(data->lang, data->type);
918 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)",
919 data->lang, data->type);
920 data->is_loaded = false;
922 SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
923 data->lang, data->type, __ttsd_get_engine_error_code(ret));
925 return TTSD_ERROR_OPERATION_FAILED;
928 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Not unload voice : default voice(%d) or ref count(%d)",
929 data->is_default, data->client_ref_count);
932 #ifdef ENGINE_AGENT_DEBUG
933 ttsd_print_voicelist();
938 int ttsd_engine_start_synthesis(const char* lang, int vctype, const char* text, int speed, const char* appid, const char* credential, void* user_param)
940 if (NULL == lang || NULL == text) {
941 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
942 return TTSD_ERROR_INVALID_PARAMETER;
945 if (false == g_agent_init) {
946 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
947 return TTSD_ERROR_OPERATION_FAILED;
950 if (false == g_engine_info->is_loaded) {
951 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
952 return TTSD_ERROR_ENGINE_NOT_FOUND;
955 /* select voice for default */
956 char* temp_lang = NULL;
958 if (true != ttsd_engine_select_valid_voice(lang, vctype, &temp_lang, &temp_type)) {
959 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to select default voice");
960 if (NULL != temp_lang) {
964 return TTSD_ERROR_INVALID_VOICE;
966 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Start synthesis : language(%s), type(%d), speed(%d), text(%s), credential(%s)",
967 (NULL == temp_lang) ? "NULL" : temp_lang, temp_type, speed, (NULL == text) ? "NULL" : text, (NULL == credential) ? "NULL" : credential);
973 temp_speed = g_engine_info->default_speed;
978 /* synthesize text */
980 ret = g_engine_info->callbacks->start_synth(temp_lang, temp_type, text, temp_speed, appid, credential, user_param);
982 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] ***************************************");
983 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] * synthesize error : %s *", __ttsd_get_engine_error_code(ret));
984 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] ***************************************");
985 if (NULL != temp_lang) {
992 if (NULL != temp_lang) {
999 int ttsd_engine_cancel_synthesis()
1001 if (false == g_agent_init) {
1002 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1003 return TTSD_ERROR_OPERATION_FAILED;
1006 if (false == g_engine_info->is_loaded) {
1007 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
1008 return TTSD_ERROR_ENGINE_NOT_FOUND;
1011 SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Cancel synth");
1012 /* stop synthesis */
1014 ret = g_engine_info->callbacks->cancel_synth();
1016 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail cancel synthesis : %s", __ttsd_get_engine_error_code(ret));
1022 bool __supported_voice_cb(const char* language, int type, void* user_data)
1024 GList** voice_list = (GList**)user_data;
1026 if (NULL == language || NULL == voice_list) {
1027 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
1031 voice_s* voice = calloc(1, sizeof(voice_s));
1032 if (NULL == voice) {
1033 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
1036 voice->language = strdup(language);
1039 *voice_list = g_list_append(*voice_list, voice);
1044 int ttsd_engine_get_voice_list(GList** voice_list)
1046 if (NULL == voice_list) {
1047 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
1048 return TTSD_ERROR_INVALID_PARAMETER;
1051 if (false == g_agent_init) {
1052 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1053 return TTSD_ERROR_OPERATION_FAILED;
1056 if (false == g_engine_info->is_loaded) {
1057 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
1058 return TTSD_ERROR_ENGINE_NOT_FOUND;
1062 ret = g_engine_info->callbacks->foreach_voices(__supported_voice_cb, (void*)voice_list);
1064 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get voice list : %s", __ttsd_get_engine_error_code(ret));
1070 int ttsd_engine_get_default_voice(char** lang, int* vctype)
1072 if (false == g_agent_init) {
1073 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1074 return TTSD_ERROR_OPERATION_FAILED;
1077 if (false == g_engine_info->is_loaded) {
1078 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
1079 return TTSD_ERROR_ENGINE_NOT_FOUND;
1082 if (NULL == lang || NULL == vctype) {
1083 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] BAD Parameter");
1084 return TTSD_ERROR_INVALID_PARAMETER;
1087 if (NULL != g_engine_info->default_lang) {
1088 *lang = strdup(g_engine_info->default_lang);
1089 *vctype = g_engine_info->default_vctype;
1091 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine] Get default voice : language(%s), type(%d)", *lang, *vctype);
1093 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Default voice is NULL");
1094 return TTSD_ERROR_OPERATION_FAILED;
1100 int ttsd_engine_set_private_data(const char* key, const char* data)
1102 if (false == g_agent_init) {
1103 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1104 return TTSD_ERROR_OPERATION_FAILED;
1107 if (false == g_engine_info->is_loaded) {
1108 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
1109 return TTSD_ERROR_ENGINE_NOT_FOUND;
1113 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
1114 return TTSD_ERROR_INVALID_PARAMETER;
1117 if (NULL == g_engine_info->callbacks->private_data_set) {
1118 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not supported feature");
1119 return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
1122 int ret = g_engine_info->callbacks->private_data_set(key, data);
1125 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set private data(%d)", ret);
1131 int ttsd_engine_get_private_data(const char* key, char** data)
1133 if (false == g_agent_init) {
1134 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1135 return TTSD_ERROR_OPERATION_FAILED;
1138 if (false == g_engine_info->is_loaded) {
1139 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
1140 return TTSD_ERROR_ENGINE_NOT_FOUND;
1143 if (NULL == key || NULL == data) {
1144 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
1145 return TTSD_ERROR_INVALID_PARAMETER;
1149 if (NULL == g_engine_info->callbacks->private_data_requested) {
1150 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not supported feature");
1151 return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
1156 ret = g_engine_info->callbacks->private_data_requested(key, &temp);
1158 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get private data(%d)", ret);
1162 *data = strdup("NULL");
1164 *data = strdup(temp);
1169 int ttsd_engine_check_app_agreed(const char* appid, bool* is_agreed)
1171 if (false == g_agent_init) {
1172 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1173 return TTSD_ERROR_OPERATION_FAILED;
1176 if (false == g_engine_info->is_loaded) {
1177 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
1178 return TTSD_ERROR_ENGINE_NOT_FOUND;
1181 if (NULL == appid || NULL == is_agreed) {
1182 SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Invalid parameter, appid is NULL");
1183 return TTSD_ERROR_NONE;
1187 if (NULL == g_engine_info->callbacks->check_app_agreed) {
1188 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not supported feature");
1189 return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
1193 bool tmp = true; // default value is true until now
1194 ret = g_engine_info->callbacks->check_app_agreed(appid, &tmp);
1196 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to check app agreed(%d)", ret);
1197 return TTSD_ERROR_OPERATION_FAILED;
1205 void __free_voice_list(GList* voice_list)
1208 voice_s* data = NULL;
1210 /* if list have item */
1211 if (g_list_length(voice_list) > 0) {
1212 /* Get a first item */
1213 iter = g_list_first(voice_list);
1215 while (NULL != iter) {
1219 if (NULL != data->language) {
1220 free(data->language);
1221 data->language = NULL;
1227 voice_list = g_list_remove_link(voice_list, iter);
1229 iter = g_list_first(voice_list);
1235 * TTS Engine Callback Functions ` *
1238 /* function for debugging */
1239 int ttsd_print_voicelist()
1242 GSList *iter = NULL;
1243 ttsvoice_s* data = NULL;
1245 SLOG(LOG_DEBUG, tts_tag(), "@@@ Voice list @@@");
1247 if (g_slist_length(g_cur_voices) > 0) {
1248 /* Get a first item */
1249 iter = g_slist_nth(g_cur_voices, 0);
1252 while (NULL != iter) {
1253 /*Get handle data from list*/
1256 if (NULL == data || NULL == data->lang) {
1257 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Data is invalid");
1261 SLOG(LOG_DEBUG, tts_tag(), "[%dth] default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
1262 i, data->is_default, data->is_loaded, data->client_ref_count, data->lang, data->type);
1265 iter = g_slist_next(iter);
1270 SLOG(LOG_DEBUG, tts_tag(), "@@@@@");
1275 int __internal_get_engine_info(ttse_request_callback_s* callback)
1277 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent DEBUG] internal get engine info");
1279 if (NULL == callback) {
1280 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
1281 return TTSD_ERROR_ENGINE_NOT_FOUND;
1284 if (NULL == callback->get_info) {
1285 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
1286 return TTSD_ERROR_ENGINE_NOT_FOUND;
1289 if (0 != callback->get_info(&(g_engine_info->engine_uuid), &(g_engine_info->engine_name), &(g_engine_info->engine_setting_path), &(g_engine_info->use_network))) {
1290 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get engine info");
1291 return TTSD_ERROR_ENGINE_NOT_FOUND;
1294 if (NULL != g_engine_info->engine_path) {
1295 free(g_engine_info->engine_path);
1296 g_engine_info->engine_path = NULL;
1298 g_engine_info->engine_path = strdup("empty");
1299 g_engine_info->is_loaded = false;
1301 if (NULL != g_engine_info->callbacks) {
1302 free(g_engine_info->callbacks);
1303 g_engine_info->callbacks = NULL;
1305 g_engine_info->callbacks = (tts_engine_callback_s*)calloc(1, sizeof(tts_engine_callback_s));
1306 if (NULL == g_engine_info->callbacks) {
1307 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
1308 return TTSD_ERROR_OUT_OF_MEMORY;
1311 g_engine_info->callbacks->get_info = callback->get_info;
1312 g_engine_info->callbacks->initialize = callback->initialize;
1313 g_engine_info->callbacks->deinitialize = callback->deinitialize;
1314 g_engine_info->callbacks->foreach_voices = callback->foreach_voices;
1315 g_engine_info->callbacks->is_valid_voice = callback->is_valid_voice;
1316 g_engine_info->callbacks->set_pitch = callback->set_pitch;
1317 g_engine_info->callbacks->load_voice = callback->load_voice;
1318 g_engine_info->callbacks->unload_voice = callback->unload_voice;
1319 g_engine_info->callbacks->start_synth = callback->start_synth;
1320 g_engine_info->callbacks->cancel_synth = callback->cancel_synth;
1321 g_engine_info->callbacks->check_app_agreed = callback->check_app_agreed;
1322 g_engine_info->callbacks->need_app_credential = callback->need_app_credential;
1324 g_engine_info->callbacks->private_data_set = NULL;
1325 g_engine_info->callbacks->private_data_requested = NULL;
1327 SLOG(LOG_DEBUG, tts_tag(), "--- Valid Engine ---");
1328 SLOG(LOG_DEBUG, tts_tag(), "Engine uuid : %s", g_engine_info->engine_uuid);
1329 SLOG(LOG_DEBUG, tts_tag(), "Engine name : %s", g_engine_info->engine_name);
1330 SLOG(LOG_DEBUG, tts_tag(), "Engine path : %s", g_engine_info->engine_path);
1331 SLOG(LOG_DEBUG, tts_tag(), "Engine setting path : %s", g_engine_info->engine_setting_path);
1332 SLOG(LOG_DEBUG, tts_tag(), "Use network : %s", g_engine_info->use_network ? "true" : "false");
1333 SLOG(LOG_DEBUG, tts_tag(), "--------------------");
1334 SLOG(LOG_DEBUG, tts_tag(), " ");
1336 return TTSD_ERROR_NONE;
1341 /** Set callbacks of the current engine */
1342 int ttsd_engine_agent_set_private_data_set_cb(ttse_private_data_set_cb callback)
1344 if (false == g_agent_init) {
1345 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1346 return TTSD_ERROR_OPERATION_FAILED;
1349 if (NULL == g_engine_info) {
1350 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] The engine is not valid");
1351 return TTSD_ERROR_INVALID_PARAMETER;
1354 if (false == g_engine_info->is_loaded) {
1355 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
1356 return TTSD_ERROR_OPERATION_FAILED;
1359 g_engine_info->callbacks->private_data_set = callback;
1361 return TTSD_ERROR_NONE;
1364 int ttsd_engine_agent_set_private_data_requested_cb(ttse_private_data_requested_cb callback)
1366 if (false == g_agent_init) {
1367 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1368 return TTSD_ERROR_OPERATION_FAILED;
1371 if (NULL == g_engine_info) {
1372 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] The engine is not valid");
1373 return TTSD_ERROR_INVALID_PARAMETER;
1376 if (false == g_engine_info->is_loaded) {
1377 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
1378 return TTSD_ERROR_OPERATION_FAILED;
1381 g_engine_info->callbacks->private_data_requested = callback;
1383 return TTSD_ERROR_NONE;