Change internal function to static
[platform/core/uifw/tts.git] / server / ttsd_engine_agent.c
1 /*
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.
12 */
13
14
15 #include <dlfcn.h>
16 #include <dirent.h>
17
18 #include "tts_defs.h"
19 #include "ttsd_main.h"
20 #include "ttsd_engine_agent.h"
21 #include "ttsd_config.h"
22
23 #define ENGINE_PATH_SIZE        256
24
25 /*
26 * Internal data structure
27 */
28 typedef struct _ttsengine_info {
29         /* base info */
30         char*   engine_uuid;
31         char*   engine_path;
32         char*   engine_name;
33         char*   engine_setting_path;
34
35         /* info for using engine load */
36         bool    is_loaded;
37         bool    use_network;
38
39         tts_engine_callback_s* callbacks;
40
41         /* engine base setting */
42         char*   default_lang;
43         int     default_vctype;
44         int     default_speed;
45         int     default_pitch;
46 } ttsengine_info_s;
47
48 typedef struct {
49         bool    is_default;
50         bool    is_loaded;
51         int     client_ref_count;
52
53         char*   lang;
54         int     type;
55 } ttsvoice_s;
56
57
58 /** Init flag */
59 static bool g_agent_init;
60
61 /** Current engine information */
62 static ttsengine_info_s* g_engine_info = NULL;
63
64 /** Current voice information */
65 static GSList* g_cur_voices = NULL;
66
67 /** Callback function for voice list */
68 static bool __supported_voice_cb(const char* language, int type, void* user_data);
69
70 /** Free voice list */
71 static void __free_voice_list(GList* voice_list);
72
73 static int ttsd_print_voicelist();
74
75 /** Get engine info */
76 static int __internal_get_engine_info(ttse_request_callback_s* callback);
77
78 static const char* __ttsd_get_engine_error_code(ttse_error_e err)
79 {
80         switch (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";
89         default:
90                 return "Invalid error code";
91         }
92 }
93
94 int ttsd_engine_agent_init()
95 {
96         if (true == g_agent_init) {
97                 SLOG(LOG_WARN, tts_tag(), "[Engine Agent] Already initialized");
98                 return TTSD_ERROR_OPERATION_FAILED;
99         }
100
101         ttsengine_info_s* temp;
102         temp = (ttsengine_info_s*)calloc(1, sizeof(ttsengine_info_s));
103         if (NULL == temp) {
104                 SLOG(LOG_WARN, tts_tag(), "[Engine Agent] Fail to alloc memory");
105                 return TTSD_ERROR_OUT_OF_MEMORY;
106         }
107
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;
113         }
114
115         SLOG(LOG_DEBUG, tts_tag(), "[Server DEBUG] language(%s), type(%d)", temp->default_lang, temp->default_vctype);
116
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;
120         }
121
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;
125         }
126
127         temp->is_loaded = false;
128         g_engine_info = temp;
129
130         g_agent_init = true;
131
132         SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Initialize Engine Agent");
133         return 0;
134 }
135
136 int ttsd_engine_agent_release()
137 {
138         if (false == g_agent_init) {
139                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
140                 return TTSD_ERROR_OPERATION_FAILED;
141         }
142
143         /* unload current engine */
144         if (g_engine_info->is_loaded) {
145                 ttsd_engine_agent_unload_current_engine();
146         }
147
148         if (NULL != g_engine_info->default_lang) {
149                 free(g_engine_info->default_lang);
150                 g_engine_info->default_lang = NULL;
151         }
152
153         if (NULL != g_engine_info->engine_uuid) {
154                 free(g_engine_info->engine_uuid);
155                 g_engine_info->engine_uuid = NULL;
156         }
157
158         if (NULL != g_engine_info->engine_name) {
159                 free(g_engine_info->engine_name);
160                 g_engine_info->engine_name = NULL;
161         }
162
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;
166         }
167
168         if (NULL != g_engine_info->engine_path) {
169                 free(g_engine_info->engine_path);
170                 g_engine_info->engine_path = NULL;
171         }
172
173         free(g_engine_info);
174         g_engine_info = NULL;
175
176         g_agent_init = false;
177
178         SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Release Engine Agent");
179
180         return 0;
181 }
182
183 static bool __set_voice_info_cb(const char* language, int type, void* user_data)
184 {
185         if (NULL == language) {
186                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
187                 return false;
188         }
189
190         ttsvoice_s* voice = calloc(1, sizeof(ttsvoice_s));
191         if (NULL == voice) {
192                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
193                 return false;
194         }
195         voice->lang = strdup(language);
196         voice->type = type;
197
198         voice->client_ref_count = 0;
199         voice->is_loaded = false;
200
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;
204         } else {
205                 voice->is_default = false;
206         }
207
208         g_cur_voices = g_slist_append(g_cur_voices, voice);
209
210         return true;
211 }
212
213 static int __update_voice_list()
214 {
215         if (false == g_agent_init) {
216                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
217                 return TTSD_ERROR_OPERATION_FAILED;
218         }
219
220         /* Get voice list */
221         if (NULL != g_cur_voices) {
222                 GSList *iter = NULL;
223                 ttsvoice_s* data = NULL;
224
225                 iter = g_slist_nth(g_cur_voices, 0);
226                 while (NULL != iter) {
227                         data = iter->data;
228
229                         if (NULL != data) {
230                                 if (NULL != data->lang) {
231                                         free(data->lang);
232                                         data->lang = NULL;
233                                 }
234
235                                 g_cur_voices = g_slist_remove(g_cur_voices, data);
236                                 free(data);
237                                 data = NULL;
238                         }
239
240                         iter = g_slist_nth(g_cur_voices, 0);
241                 }
242         }
243
244         g_cur_voices = NULL;
245
246         int ret = -1;
247         ret = g_engine_info->callbacks->foreach_voices(__set_voice_info_cb, NULL);
248
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);
251                 return -1;
252         }
253
254 #ifdef ENGINE_AGENT_DEBUG
255         ttsd_print_voicelist();
256 #endif
257         return 0;
258 }
259
260 int ttsd_engine_agent_load_current_engine(ttse_request_callback_s* callback)
261 {
262         SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent DEBUG] load current engine START");
263
264
265         if (false == g_agent_init) {
266                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
267                 return TTSD_ERROR_OPERATION_FAILED;
268         }
269
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 ");
273                 return 0;
274         }
275
276         if (NULL == callback) {
277                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
278                 return TTSD_ERROR_ENGINE_NOT_FOUND;
279         }
280
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;
290         }
291
292         /* Get current engine info */
293         int ret = __internal_get_engine_info(callback);
294         if (0 != ret) {
295                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get engine info");
296                 return ret;
297         }
298
299         /* Initialize engine */
300         ret = g_engine_info->callbacks->initialize();
301         if (0 != ret) {
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;
304         }
305
306         /* Get voice info of current engine */
307         ret = __update_voice_list();
308         if (0 != ret) {
309                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set voice info : result(%d)", ret);
310                 return TTSD_ERROR_OPERATION_FAILED;
311         }
312
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);
317                 if (0 == ret) {
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);
321                         } else {
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);
324
325                                 /* TODO - Error Tolerance when Default voice is not valid */
326                                 return TTSD_ERROR_OPERATION_FAILED;
327                         }
328                 } else {
329                         SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail(Engine ERROR) : %s", __ttsd_get_engine_error_code(ret));
330                         return ret;
331                 }
332         }
333
334         /* load default voice */
335         ret = g_engine_info->callbacks->load_voice(g_engine_info->default_lang, g_engine_info->default_vctype);
336         if (0 == ret) {
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);
339         } else {
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));
342
343                 return TTSD_ERROR_OPERATION_FAILED;
344         }
345
346         /* set default pitch */
347         ret = g_engine_info->callbacks->set_pitch(g_engine_info->default_pitch);
348         if (0 != ret) {
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));
351                 return ret;
352         } else {
353                 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set default pitch : pitch(%d)", g_engine_info->default_pitch);
354         }
355
356         g_engine_info->is_loaded = true;
357
358         return 0;
359 }
360
361 int ttsd_engine_agent_unload_current_engine()
362 {
363         if (false == g_agent_init) {
364                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
365                 return TTSD_ERROR_OPERATION_FAILED;
366         }
367
368         if (false == g_engine_info->is_loaded) {
369                 SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Engine has already been unloaded ");
370                 return 0;
371         }
372
373         /* shutdown engine */
374         int ret = 0;
375         ret = g_engine_info->callbacks->deinitialize();
376         if (0 != ret) {
377                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent] Fail deinitialize() : %s", __ttsd_get_engine_error_code(ret));
378         }
379
380         /* reset current engine data */
381         g_engine_info->is_loaded = false;
382
383         GSList *iter = NULL;
384         ttsvoice_s* data = NULL;
385
386         iter = g_slist_nth(g_cur_voices, 0);
387         while (NULL != iter) {
388                 data = iter->data;
389
390                 if (NULL != data) {
391                         if (NULL != data->lang) {
392                                 free(data->lang);
393                                 data->lang = NULL;
394                         }
395                         g_cur_voices = g_slist_remove(g_cur_voices, data);
396                         free(data);
397                         data = NULL;
398                 }
399
400                 iter = g_slist_nth(g_cur_voices, 0);
401         }
402
403         SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent Success] Unload current engine");
404
405         return 0;
406 }
407
408 bool ttsd_engine_agent_need_network()
409 {
410         if (false == g_agent_init) {
411                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
412                 return TTSD_ERROR_OPERATION_FAILED;
413         }
414
415         return g_engine_info->use_network;
416 }
417
418 bool ttsd_engine_agent_is_same_engine(const char* engine_id)
419 {
420         if (false == g_agent_init) {
421                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
422                 return false;
423         }
424
425         if (NULL == engine_id) {
426                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] engine_id is NULL");
427                 return false;
428         }
429
430         if (NULL == g_engine_info) {
431                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
432                 return false;
433         }
434
435         if (false == g_engine_info->is_loaded) {
436                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
437                 return false;
438         }
439
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))) {
442                 return true;
443         }
444
445         return false;
446 }
447
448 bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, int* out_type)
449 {
450         if (NULL == lang || NULL == out_lang || NULL == out_type) {
451                 return false;
452         }
453
454         if (NULL == g_engine_info) {
455                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
456                 return false;
457         }
458
459         if (false == g_engine_info->is_loaded) {
460                 SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Not loaded engine");
461                 return false;
462         }
463
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);
466
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);
471                 } else {
472                         *out_lang = NULL;
473                 }
474
475                 *out_type = g_engine_info->default_vctype;
476                 return true;
477         }
478
479         /* Get voice list */
480         GList* voice_list = NULL;
481         int ret = 0;
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);
485                 return false;
486         }
487
488         bool result;
489         result = false;
490
491         GList *iter = NULL;
492         voice_s* voice;
493
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);
497
498                 while (NULL != iter) {
499                         /* Get handle data from list */
500                         voice = iter->data;
501
502                         if (0 == strncmp(voice->language, lang, strlen(lang)) &&  voice->type == type) {
503                                 *out_lang = strdup(voice->language);
504                                 *out_type = voice->type;
505                                 result = true;
506                                 break;
507                         }
508
509                         iter = g_list_next(iter);
510                 }
511
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;
517                         result = true;
518                 } else {
519                         voice_s* voice_selected = NULL;
520                         iter = g_list_first(voice_list);
521                         while (NULL != iter) {
522                                 /* Get handle data from list */
523                                 voice = iter->data;
524
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;
529                                                 break;
530                                         }
531                                 }
532                                 iter = g_list_next(iter);
533                         }
534
535                         if (NULL != voice_selected) {
536                                 *out_lang = strdup(voice_selected->language);
537                                 *out_type = voice_selected->type;
538                                 result = true;
539                         }
540                 }
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;
546                         result = true;
547                 } else {
548                         voice_s* voice_selected = NULL;
549                         iter = g_list_first(voice_list);
550                         while (NULL != iter) {
551                                 /* Get handle data from list */
552                                 voice = iter->data;
553
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;
558                                                 break;
559                                         }
560                                 }
561                                 iter = g_list_next(iter);
562                         }
563
564                         if (NULL != voice_selected) {
565                                 *out_lang = strdup(voice->language);
566                                 *out_type = voice_selected->type;
567                                 result = true;
568                         }
569                 }
570         }
571
572         if (true == result) {
573                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Selected voice : lang(%s), type(%d)", *out_lang, *out_type);
574         }
575
576         __free_voice_list(voice_list);
577
578         return result;
579 }
580
581
582
583 int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
584 {
585         if (NULL == language) {
586                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] language is NULL");
587                 return false;
588         }
589
590         if (false == g_agent_init) {
591                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
592                 return TTSD_ERROR_OPERATION_FAILED;
593         }
594
595         if (NULL == g_engine_info) {
596                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
597                 return false;
598         }
599
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;
603         }
604
605         int ret = -1;
606         bool is_valid = false;
607         ret = g_engine_info->callbacks->is_valid_voice(language, vctype, &is_valid);
608         if (0 == ret) {
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);
612                 } else {
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);
615
616                         return TTSD_ERROR_OPERATION_FAILED;
617                 }
618         } else {
619                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail(Engine ERROR) : %s", __ttsd_get_engine_error_code(ret));
620                 return ret;
621         }
622
623
624         GSList *iter = NULL;
625         ttsvoice_s* data = NULL;
626
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 */
631                 data = iter->data;
632
633                 if (NULL == data) {
634                         SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Voice data is NULL");
635                         return TTSD_ERROR_OPERATION_FAILED;
636                 }
637
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) {
642                                 /* load voice */
643                                         ret = g_engine_info->callbacks->load_voice(data->lang, data->type);
644                                         if (0 == ret) {
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;
648                                         } else {
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));
651                                         }
652                                 }
653                         }
654                         break;
655                 }
656
657                 /*Get next item*/
658                 iter = g_slist_next(iter);
659         }
660
661 #ifdef ENGINE_AGENT_DEBUG
662         ttsd_print_voicelist();
663 #endif
664
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*/
669                 data = iter->data;
670
671                 if (NULL == data) {
672                         SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Voice data is NULL");
673                         return TTSD_ERROR_OPERATION_FAILED;
674                 }
675
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) {
679                                 /* Unload voice */
680                                 ret = g_engine_info->callbacks->unload_voice(data->lang, data->type);
681                                 if (0 == ret) {
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;
685                                 } else {
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));
688                                 }
689                         }
690                         break;
691                 }
692
693                 /*Get next item*/
694                 iter = g_slist_next(iter);
695         }
696
697         if (NULL != g_engine_info->default_lang) {
698                 free(g_engine_info->default_lang);
699                 g_engine_info->default_lang = NULL;
700         }
701
702         g_engine_info->default_lang = strdup(language);
703         g_engine_info->default_vctype = vctype;
704
705 #ifdef ENGINE_AGENT_DEBUG
706         ttsd_print_voicelist();
707 #endif
708
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);
711
712         return 0;
713 }
714
715 int ttsd_engine_agent_set_default_speed(int speed)
716 {
717         if (false == g_agent_init) {
718                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
719                 return TTSD_ERROR_OPERATION_FAILED;
720         }
721
722         g_engine_info->default_speed = speed;
723
724         return 0;
725 }
726
727 int ttsd_engine_agent_set_default_pitch(int pitch)
728 {
729         if (false == g_agent_init) {
730                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
731                 return TTSD_ERROR_OPERATION_FAILED;
732         }
733
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;
737         }
738
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;
742         }
743
744         int ret = g_engine_info->callbacks->set_pitch(pitch);
745         if (0 != ret) {
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;
749         }
750
751         g_engine_info->default_pitch = pitch;
752
753         SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Set pitch(%d)", pitch);
754         return 0;
755 }
756
757 int ttsd_engine_agent_is_credential_needed(int uid, bool* credential_needed)
758 {
759         if (NULL == credential_needed) {
760                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid Parameter");
761                 return TTSD_ERROR_INVALID_PARAMETER;
762         }
763
764         if (false == g_agent_init) {
765                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
766                 return TTSD_ERROR_OPERATION_FAILED;
767         }
768
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;
772         }
773
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;
777         }
778
779         bool result = false;
780         result = g_engine_info->callbacks->need_app_credential();
781         *credential_needed = result;
782
783         SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Need app credential, credential_needed(%d)", *credential_needed);
784         return TTSD_ERROR_NONE;
785 }
786
787 /******************************************************************************************
788 * TTS Engine Interfaces for client
789 *******************************************************************************************/
790
791 int ttsd_engine_load_voice(const char* lang, const int vctype)
792 {
793         if (false == g_agent_init) {
794                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
795                 return TTSD_ERROR_OPERATION_FAILED;
796         }
797
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;
801         }
802
803         if (NULL == lang) {
804                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No language parameter");
805                 return TTSD_ERROR_INVALID_PARAMETER;
806         }
807
808         /* 1. Find voice info */
809         int ret = -1;
810         GSList *iter = NULL;
811         ttsvoice_s* data = NULL;
812
813         iter = g_slist_nth(g_cur_voices, 0);
814         while (NULL != iter) {
815                 /*Get handle data from list*/
816                 data = iter->data;
817
818                 if (NULL != data) {
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);
822                                 break;
823                         }
824                 }
825
826                 /*Get next item*/
827                 iter = g_slist_next(iter);
828                 data = NULL;
829         }
830
831         if (NULL == data) {
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;
834         }
835
836         /* 2. increase ref count */
837         data->client_ref_count++;
838
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) {
841                 /* load voice */
842                 ret = g_engine_info->callbacks->load_voice(data->lang, data->type);
843                 if (0 == ret) {
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;
847                 } else {
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));
850
851                         return TTSD_ERROR_OPERATION_FAILED;
852                 }
853         } else {
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);
856         }
857
858 #ifdef ENGINE_AGENT_DEBUG
859         ttsd_print_voicelist();
860 #endif
861
862         return 0;
863 }
864
865 int ttsd_engine_unload_voice(const char* lang, const int vctype)
866 {
867         if (false == g_agent_init) {
868                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
869                 return TTSD_ERROR_OPERATION_FAILED;
870         }
871
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;
875         }
876
877         if (NULL == lang) {
878                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No language parameter");
879                 return TTSD_ERROR_INVALID_PARAMETER;
880         }
881
882         /* 1. Find voice info */
883         int ret = -1;
884         GSList *iter = NULL;
885         ttsvoice_s* data = NULL;
886
887         iter = g_slist_nth(g_cur_voices, 0);
888         while (NULL != iter) {
889                 /*Get handle data from list*/
890                 data = iter->data;
891
892                 if (NULL != data) {
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);
896                                 break;
897                         }
898                 }
899
900                 /*Get next item*/
901                 iter = g_slist_next(iter);
902                 data = NULL;
903         }
904
905         if (NULL == data) {
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;
908         }
909
910         /* 2. Decrease ref count */
911         data->client_ref_count--;
912
913         /* 3. if ref count change 0 and not default, load voice */
914         if (0 == data->client_ref_count && false == data->is_default) {
915                 /* unload voice */
916                 ret = g_engine_info->callbacks->unload_voice(data->lang, data->type);
917                 if (0 == ret) {
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;
921                 } else {
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));
924
925                         return TTSD_ERROR_OPERATION_FAILED;
926                 }
927         } else {
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);
930         }
931
932 #ifdef ENGINE_AGENT_DEBUG
933         ttsd_print_voicelist();
934 #endif
935         return 0;
936 }
937
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)
939 {
940         if (NULL == lang || NULL == text) {
941                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
942                 return TTSD_ERROR_INVALID_PARAMETER;
943         }
944
945         if (false == g_agent_init) {
946                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
947                 return TTSD_ERROR_OPERATION_FAILED;
948         }
949
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;
953         }
954
955         /* select voice for default */
956         char* temp_lang = NULL;
957         int temp_type;
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) {
961                         free(temp_lang);
962                         temp_lang = NULL;
963                 }
964                 return TTSD_ERROR_INVALID_VOICE;
965         } else {
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);
968         }
969
970         int temp_speed;
971
972         if (0 == speed) {
973                 temp_speed = g_engine_info->default_speed;
974         } else {
975                 temp_speed = speed;
976         }
977
978         /* synthesize text */
979         int ret = 0;
980         ret = g_engine_info->callbacks->start_synth(temp_lang, temp_type, text, temp_speed, appid, credential, user_param);
981         if (0 != ret) {
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) {
986                         free(temp_lang);
987                         temp_lang = NULL;
988                 }
989                 return ret;
990         }
991
992         if (NULL != temp_lang)  {
993                 free(temp_lang);
994                 temp_lang = NULL;
995         }
996         return 0;
997 }
998
999 int ttsd_engine_cancel_synthesis()
1000 {
1001         if (false == g_agent_init) {
1002                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1003                 return TTSD_ERROR_OPERATION_FAILED;
1004         }
1005
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;
1009         }
1010
1011         SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Cancel synth");
1012         /* stop synthesis */
1013         int ret = 0;
1014         ret = g_engine_info->callbacks->cancel_synth();
1015         if (0 != ret) {
1016                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail cancel synthesis : %s", __ttsd_get_engine_error_code(ret));
1017         }
1018
1019         return ret;
1020 }
1021
1022 bool __supported_voice_cb(const char* language, int type, void* user_data)
1023 {
1024         GList** voice_list = (GList**)user_data;
1025
1026         if (NULL == language || NULL == voice_list) {
1027                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
1028                 return false;
1029         }
1030
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");
1034                 return false;
1035         }
1036         voice->language = strdup(language);
1037         voice->type = type;
1038
1039         *voice_list = g_list_append(*voice_list, voice);
1040
1041         return true;
1042 }
1043
1044 int ttsd_engine_get_voice_list(GList** voice_list)
1045 {
1046         if (NULL == voice_list) {
1047                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
1048                 return TTSD_ERROR_INVALID_PARAMETER;
1049         }
1050
1051         if (false == g_agent_init) {
1052                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1053                 return TTSD_ERROR_OPERATION_FAILED;
1054         }
1055
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;
1059         }
1060
1061         int ret = 0;
1062         ret = g_engine_info->callbacks->foreach_voices(__supported_voice_cb, (void*)voice_list);
1063         if (0 != ret) {
1064                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get voice list : %s", __ttsd_get_engine_error_code(ret));
1065         }
1066
1067         return ret;
1068 }
1069
1070 int ttsd_engine_get_default_voice(char** lang, int* vctype)
1071 {
1072         if (false == g_agent_init) {
1073                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1074                 return TTSD_ERROR_OPERATION_FAILED;
1075         }
1076
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;
1080         }
1081
1082         if (NULL == lang || NULL == vctype) {
1083                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] BAD Parameter");
1084                 return TTSD_ERROR_INVALID_PARAMETER;
1085         }
1086
1087         if (NULL != g_engine_info->default_lang) {
1088                 *lang = strdup(g_engine_info->default_lang);
1089                 *vctype = g_engine_info->default_vctype;
1090
1091                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine] Get default voice : language(%s), type(%d)", *lang, *vctype);
1092         } else {
1093                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Default voice is NULL");
1094                 return TTSD_ERROR_OPERATION_FAILED;
1095         }
1096
1097         return 0;
1098 }
1099
1100 int ttsd_engine_set_private_data(const char* key, const char* data)
1101 {
1102         if (false == g_agent_init) {
1103                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1104                 return TTSD_ERROR_OPERATION_FAILED;
1105         }
1106
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;
1110         }
1111
1112         if (NULL == key) {
1113                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
1114                 return TTSD_ERROR_INVALID_PARAMETER;
1115         }
1116
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;
1120         }
1121
1122         int ret = g_engine_info->callbacks->private_data_set(key, data);
1123
1124         if (0 != ret) {
1125                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set private data(%d)", ret);
1126         }
1127
1128         return ret;
1129 }
1130
1131 int ttsd_engine_get_private_data(const char* key, char** data)
1132 {
1133         if (false == g_agent_init) {
1134                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1135                 return TTSD_ERROR_OPERATION_FAILED;
1136         }
1137
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;
1141         }
1142
1143         if (NULL == key || NULL == data) {
1144                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
1145                 return TTSD_ERROR_INVALID_PARAMETER;
1146         }
1147
1148
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;
1152         }
1153
1154         char* temp = NULL;
1155         int ret = 0;
1156         ret = g_engine_info->callbacks->private_data_requested(key, &temp);
1157         if (0 != ret) {
1158                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get private data(%d)", ret);
1159         }
1160
1161         if (NULL == temp)
1162                 *data = strdup("NULL");
1163         else
1164                 *data = strdup(temp);
1165
1166         return ret;
1167 }
1168
1169 int ttsd_engine_check_app_agreed(const char* appid, bool* is_agreed)
1170 {
1171         if (false == g_agent_init) {
1172                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1173                 return TTSD_ERROR_OPERATION_FAILED;
1174         }
1175
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;
1179         }
1180
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;
1184         }
1185
1186
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;
1190         }
1191
1192         int ret = 0;
1193         bool tmp = true; // default value is true until now
1194         ret = g_engine_info->callbacks->check_app_agreed(appid, &tmp);
1195         if (0 != ret) {
1196                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to check app agreed(%d)", ret);
1197                 return TTSD_ERROR_OPERATION_FAILED;
1198         }
1199
1200         *is_agreed = tmp;
1201
1202         return ret;
1203 }
1204
1205 void __free_voice_list(GList* voice_list)
1206 {
1207         GList *iter = NULL;
1208         voice_s* data = NULL;
1209
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);
1214
1215                 while (NULL != iter) {
1216                         data = iter->data;
1217
1218                         if (NULL != data) {
1219                                 if (NULL != data->language) {
1220                                         free(data->language);
1221                                         data->language = NULL;
1222                                 }
1223                                 free(data);
1224                                 data = NULL;
1225                         }
1226
1227                         voice_list = g_list_remove_link(voice_list, iter);
1228                         g_list_free(iter);
1229                         iter = g_list_first(voice_list);
1230                 }
1231         }
1232 }
1233
1234 /*
1235 * TTS Engine Callback Functions                                                                                 `                                 *
1236 */
1237
1238 /* function for debugging */
1239 int ttsd_print_voicelist()
1240 {
1241         /* Test log */
1242         GSList *iter = NULL;
1243         ttsvoice_s* data = NULL;
1244
1245         SLOG(LOG_DEBUG, tts_tag(), "@@@ Voice list @@@");
1246
1247         if (g_slist_length(g_cur_voices) > 0) {
1248                 /* Get a first item */
1249                 iter = g_slist_nth(g_cur_voices, 0);
1250
1251                 int i = 1;
1252                 while (NULL != iter) {
1253                         /*Get handle data from list*/
1254                         data = iter->data;
1255
1256                         if (NULL == data || NULL == data->lang) {
1257                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Data is invalid");
1258                                 return 0;
1259                         }
1260
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);
1263
1264                         /*Get next item*/
1265                         iter = g_slist_next(iter);
1266                         i++;
1267                 }
1268         }
1269
1270         SLOG(LOG_DEBUG, tts_tag(), "@@@@@");
1271
1272         return 0;
1273 }
1274
1275 static int __internal_get_engine_info(ttse_request_callback_s* callback)
1276 {
1277         SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent DEBUG] internal get engine info");
1278
1279         if (NULL == callback) {
1280                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
1281                 return TTSD_ERROR_ENGINE_NOT_FOUND;
1282         }
1283
1284         if (NULL == callback->get_info) {
1285                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
1286                 return TTSD_ERROR_ENGINE_NOT_FOUND;
1287         }
1288
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;
1292         }
1293
1294         if (NULL != g_engine_info->engine_path) {
1295                 free(g_engine_info->engine_path);
1296                 g_engine_info->engine_path = NULL;
1297         }
1298         g_engine_info->engine_path = strdup("empty");
1299         g_engine_info->is_loaded = false;
1300
1301         if (NULL != g_engine_info->callbacks) {
1302                 free(g_engine_info->callbacks);
1303                 g_engine_info->callbacks = NULL;
1304         }
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;
1309         }
1310
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;
1323
1324         g_engine_info->callbacks->private_data_set = NULL;
1325         g_engine_info->callbacks->private_data_requested = NULL;
1326
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(), "  ");
1335
1336         return TTSD_ERROR_NONE;
1337
1338 }
1339
1340
1341 /** Set callbacks of the current engine */
1342 int ttsd_engine_agent_set_private_data_set_cb(ttse_private_data_set_cb callback)
1343 {
1344         if (false == g_agent_init) {
1345                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1346                 return TTSD_ERROR_OPERATION_FAILED;
1347         }
1348
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;
1352         }
1353
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;
1357         }
1358
1359         g_engine_info->callbacks->private_data_set = callback;
1360
1361         return TTSD_ERROR_NONE;
1362 }
1363
1364 int ttsd_engine_agent_set_private_data_requested_cb(ttse_private_data_requested_cb callback)
1365 {
1366         if (false == g_agent_init) {
1367                 SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
1368                 return TTSD_ERROR_OPERATION_FAILED;
1369         }
1370
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;
1374         }
1375
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;
1379         }
1380
1381         g_engine_info->callbacks->private_data_requested = callback;
1382
1383         return TTSD_ERROR_NONE;
1384 }
1385
1386