Merge with Tizen 2.3
[platform/core/uifw/tts.git] / server / ttsd_engine_agent.c
1 /*
2 *  Copyright (c) 2011-2014 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 {
29         /* base info */
30         char*   engine_uuid;
31         char*   engine_name; 
32         char*   engine_path;
33
34         /* info for using engine load */
35         bool    is_set;
36         bool    is_loaded;              
37         bool    need_network;
38         void    *handle;
39
40         /* engine base setting */
41         char*   default_lang;
42         int     default_vctype;
43         int     default_speed;
44         int     default_pitch;
45
46         ttspe_funcs_s*  pefuncs;
47         ttspd_funcs_s*  pdfuncs;
48
49         int (*ttsp_load_engine)(const ttspd_funcs_s* pdfuncs, ttspe_funcs_s* pefuncs);
50         int (*ttsp_unload_engine)();
51 }ttsengine_s;
52
53 typedef struct {
54         char*   engine_uuid;
55         char*   engine_path;
56         char*   engine_name;
57         char*   setting_ug_path;
58         bool    use_network;
59 }ttsengine_info_s;
60
61 typedef struct 
62 {
63         bool    is_default;
64         bool    is_loaded;
65         int     client_ref_count;
66
67         char*   lang;
68         int     type;
69 }ttsvoice_s;
70
71
72 /** Init flag */
73 static bool g_agent_init;
74
75 /** TTS engine list */
76 static GList *g_engine_list;
77
78 /** Current engine information */
79 static ttsengine_s g_cur_engine;
80
81 /** Current voice information */
82 static GSList* g_cur_voices;
83
84 /** Result callback function */
85 static synth_result_callback g_result_cb;
86
87
88 /** Set current engine */
89 int __internal_set_current_engine(const char* engine_uuid);
90
91 /** Check engine id */
92 int __internal_check_engine_id(const char* engine_uuid);
93
94 /** Update engine list */
95 int __internal_update_engine_list();
96
97 /** Get engine info */
98 int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info);
99
100 /** Callback function for result */
101 bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, 
102                  ttsp_audio_type_e audio_type, int rate, void *user_data);
103
104 /** Callback function for voice list */
105 bool __supported_voice_cb(const char* language, int type, void* user_data);
106
107 /** Free voice list */
108 void __free_voice_list(GList* voice_list);
109
110 /** Callback function for engine info */
111 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
112                       bool use_network, void* user_data);
113
114 /** Callback fucntion for engine setting */
115 bool __engine_setting_cb(const char* key, const char* value, void* user_data);
116
117
118 /** Print list */
119 int ttsd_print_enginelist();
120
121 int ttsd_print_voicelist();
122
123 static const char* __ttsd_get_engine_error_code(ttsp_error_e err)
124 {
125         switch(err) {
126         case TTSP_ERROR_NONE:                   return "TTSP_ERROR_NONE";
127         case TTSP_ERROR_OUT_OF_MEMORY:          return "TTSP_ERROR_OUT_OF_MEMORY";
128         case TTSP_ERROR_IO_ERROR:               return "TTSP_ERROR_IO_ERROR";
129         case TTSP_ERROR_INVALID_PARAMETER:      return "TTSP_ERROR_INVALID_PARAMETER";
130         case TTSP_ERROR_OUT_OF_NETWORK:         return "TTSP_ERROR_OUT_OF_NETWORK";
131         case TTSP_ERROR_INVALID_STATE:          return "TTSP_ERROR_INVALID_STATE";
132         case TTSP_ERROR_INVALID_VOICE:          return "TTSP_ERROR_INVALID_VOICE";
133         case TTSP_ERROR_OPERATION_FAILED:       return "TTSP_ERROR_OPERATION_FAILED";
134         default:
135                 return "Invalid error code";
136         }
137 }
138
139 int ttsd_engine_agent_init(synth_result_callback result_cb)
140 {
141         /* initialize static data */
142         if (result_cb == NULL) {
143                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] invalid parameter");
144                 return TTSD_ERROR_INVALID_PARAMETER;
145         }
146
147         g_result_cb = result_cb;
148
149         g_cur_engine.engine_uuid = NULL;
150         g_cur_engine.engine_name = NULL;
151         g_cur_engine.engine_path = NULL;
152
153         g_cur_engine.is_set = false;
154         g_cur_engine.handle = NULL;
155         g_cur_engine.pefuncs = (ttspe_funcs_s*)calloc(1, sizeof(ttspe_funcs_s));
156         g_cur_engine.pdfuncs = (ttspd_funcs_s*)calloc(1, sizeof(ttspd_funcs_s));
157
158         g_agent_init = true;
159
160         if (0 != ttsd_config_get_default_voice(&(g_cur_engine.default_lang), &(g_cur_engine.default_vctype))) {
161                 SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default voice in config"); 
162                 /* Set default voice */
163                 g_cur_engine.default_lang = strdup(TTS_BASE_LANGUAGE);
164                 g_cur_engine.default_vctype = TTSP_VOICE_TYPE_FEMALE;
165         }
166
167         if (0 != ttsd_config_get_default_speed(&(g_cur_engine.default_speed))) {
168                 SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default speed in config"); 
169                 g_cur_engine.default_speed = TTS_SPEED_NORMAL;
170         }
171
172         if (0 != ttsd_config_get_default_pitch(&(g_cur_engine.default_pitch))) {
173                 SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default pitch in config"); 
174                 g_cur_engine.default_pitch = TTS_PITCH_NORMAL;
175         }
176
177         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Initialize Engine Agent");
178
179         return 0;
180 }
181
182 int ttsd_engine_agent_release()
183 {
184         if (false == g_agent_init) {
185                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
186                 return TTSD_ERROR_OPERATION_FAILED;
187         }
188
189         /* unload current engine */
190         ttsd_engine_agent_unload_current_engine();
191
192         /* release engine list */
193         GList *iter = NULL;
194         ttsengine_info_s *data = NULL;
195
196         if (g_list_length(g_engine_list) > 0) {
197                 /* Get a first item */
198                 iter = g_list_first(g_engine_list);
199                 while (NULL != iter) {
200                         /* Get data from item */
201                         data = iter->data;
202                         iter = g_list_remove(iter, data);
203
204                         if (NULL != data) {
205                                 if (NULL != data->engine_uuid)          free(data->engine_uuid);
206                                 if (NULL != data->engine_name)          free(data->engine_name);
207                                 if (NULL != data->setting_ug_path)      free(data->setting_ug_path);
208                                 if (NULL != data->engine_path)          free(data->engine_path);
209                                 free(data);
210                         }
211                 }
212         }
213         g_list_free(iter);
214
215         /* release current engine data */
216         if (g_cur_engine.engine_uuid != NULL)   free(g_cur_engine.engine_uuid);
217         if (g_cur_engine.engine_name != NULL)   free(g_cur_engine.engine_name);
218         if (g_cur_engine.engine_path != NULL)   free(g_cur_engine.engine_path);
219
220         if (g_cur_engine.pefuncs != NULL)       free(g_cur_engine.pefuncs);
221         if (g_cur_engine.pdfuncs != NULL)       free(g_cur_engine.pdfuncs);
222         if (g_cur_engine.default_lang != NULL)  free(g_cur_engine.default_lang);
223         g_result_cb = NULL;
224         g_agent_init = false;
225
226         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Release Engine Agent");
227
228         return 0;
229 }
230
231 int ttsd_engine_agent_initialize_current_engine()
232 {
233         if (false == g_agent_init) {
234                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
235                 return TTSD_ERROR_OPERATION_FAILED;
236         }
237
238         /* update engine list */
239         if (0 != __internal_update_engine_list()) {
240                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] No engine error");
241                 return TTSD_ERROR_OPERATION_FAILED;
242         }
243
244         /* 2. get current engine from config */
245         char* cur_engine_uuid = NULL;
246         bool is_get_engineid_from_config = false;
247
248         if (0 != ttsd_config_get_default_engine(&cur_engine_uuid)) {
249                 /*not set current engine */
250                 /*set system default engine*/
251                 GList *iter = NULL;
252                 ttsengine_info_s *data = NULL;
253
254                 if (g_list_length(g_engine_list) > 0) {
255                         iter = g_list_first(g_engine_list);
256                         data = iter->data;
257
258                         if (NULL != data) {
259                                 if (NULL != data->engine_uuid) {
260                                         cur_engine_uuid = strdup(data->engine_uuid);
261                                         ttsd_config_set_default_engine(cur_engine_uuid);
262                                 } else {
263                                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Data of current engine is corrupt");
264                                         return TTSD_ERROR_OPERATION_FAILED;
265                                 }
266                         }
267                 } else {
268                         SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Fail to set a engine of engine list");
269                         return TTSD_ERROR_OPERATION_FAILED;     
270                 }
271                 
272                 is_get_engineid_from_config = false;
273         } else {
274                 is_get_engineid_from_config = true;
275         }
276
277         if (NULL == cur_engine_uuid) {
278                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Current engine id is NULL");
279                         return TTSD_ERROR_OPERATION_FAILED;
280         }
281
282         /* check whether cur engine uuid is valid or not. */
283         if (0 != __internal_check_engine_id(cur_engine_uuid)) {
284                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] It is not valid engine id from config");
285
286                 GList *iter = NULL;
287                 
288                 if (g_list_length(g_engine_list) > 0) 
289                         iter = g_list_first(g_engine_list);
290                 else {
291                         SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] NO TTS Engine !!");
292                         if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
293                         return TTSD_ERROR_OPERATION_FAILED;     
294                 }
295
296                 if (cur_engine_uuid != NULL)    free(cur_engine_uuid);
297                 ttsengine_info_s *data = NULL;
298                 data = iter->data;
299
300                 cur_engine_uuid = strdup(data->engine_uuid);
301
302                 is_get_engineid_from_config = false;
303         }
304
305         if (NULL != cur_engine_uuid) 
306                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Current Engine Id : %s", cur_engine_uuid);
307         else 
308                 return TTSD_ERROR_OPERATION_FAILED;
309
310         /* set current engine */
311         if (0 != __internal_set_current_engine(cur_engine_uuid)) {
312                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to set current engine ");
313                 if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
314                 return TTSD_ERROR_OPERATION_FAILED;
315         } 
316
317         if (false == is_get_engineid_from_config) {
318                 if (0 != ttsd_config_set_default_engine(cur_engine_uuid)) {
319                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to set id to config");
320                 }
321         }
322
323         if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
324
325         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set current engine"); 
326
327         return 0;
328 }
329
330 int __internal_check_engine_id(const char* engine_uuid)
331 {
332         GList *iter = NULL;
333         ttsengine_s *data = NULL;
334
335         if (g_list_length(g_engine_list) > 0) {
336                 iter = g_list_first(g_engine_list);
337
338                 while (NULL != iter) {
339                         data = iter->data;
340
341                         if (0 == strncmp(engine_uuid, data->engine_uuid, strlen(data->engine_uuid))) 
342                                 return 0;
343         
344                         iter = g_list_next(iter);
345                 }
346         }
347
348         return -1;
349 }
350
351 void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
352                              bool use_network, void* user_data)
353 {
354         ttsengine_info_s* temp = (ttsengine_info_s*)user_data; 
355
356         if (NULL != engine_uuid)
357                 temp->engine_uuid = strdup(engine_uuid);
358         
359         if (NULL != engine_name)
360                 temp->engine_name = strdup(engine_name);
361
362         if (NULL != setting_ug_name)
363                 temp->setting_ug_path = strdup(setting_ug_name);
364
365         temp->use_network = use_network;
366         return;
367 }
368
369 int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info)
370 {
371         char *error;
372         void* handle;
373
374         handle = dlopen(filepath, RTLD_LAZY);
375
376         if (!handle) {
377                 SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Invalid engine : %s", filepath); 
378                 return TTSD_ERROR_OPERATION_FAILED;
379         }
380
381         /* link engine to daemon */
382         dlsym(handle, "ttsp_load_engine");
383         if ((error = dlerror()) != NULL) {
384                 SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_load_engine : path(%s) message(%s)", filepath, error);
385                 dlclose(handle);
386                 return TTSD_ERROR_OPERATION_FAILED;
387         }
388
389         dlsym(handle, "ttsp_unload_engine");
390         if ((error = dlerror()) != NULL) {
391                 SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_unload_engine : path(%s) message(%s)", filepath, error);
392                 dlclose(handle);
393                 return TTSD_ERROR_OPERATION_FAILED;
394         }
395
396         int (*get_engine_info)(ttsp_engine_info_cb callback, void* user_data);
397
398         get_engine_info = (int (*)(ttsp_engine_info_cb, void*))dlsym(handle, "ttsp_get_engine_info");
399         if (NULL != (error = dlerror()) || NULL == get_engine_info) {
400                 SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_get_engine_info() :path(%s) message(%s)", filepath, error);
401                 dlclose(handle);
402                 return TTSD_ERROR_OPERATION_FAILED;
403         }
404
405         ttsengine_info_s* temp;
406         temp = (ttsengine_info_s*)calloc(1, sizeof(ttsengine_info_s));
407         if (NULL == temp) {
408                 SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to alloc memory");
409                 dlclose(handle);
410                 return TTSD_ERROR_OUT_OF_MEMORY;
411         }
412
413         /* get engine info */
414         if (0 != get_engine_info(&__engine_info_cb, (void*)temp)) {
415                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get engine info");
416                 dlclose(handle);
417                 free(temp);
418                 return TTSD_ERROR_OPERATION_FAILED;
419         }
420
421         /* close engine */
422         dlclose(handle);
423
424         if (TTSD_MODE_SCREEN_READER == ttsd_get_mode() && true == temp->use_network) {
425                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent WARNING] %s is invalid because of network based", temp->engine_name);
426                 if (NULL != temp->engine_uuid)          free(temp->engine_uuid);
427                 if (NULL != temp->engine_name)          free(temp->engine_name);
428                 if (NULL != temp->setting_ug_path)      free(temp->setting_ug_path);
429                 free(temp);
430                 return TTSD_ERROR_OPERATION_FAILED;
431         }
432
433         temp->engine_path = strdup(filepath);
434         
435         SLOG(LOG_DEBUG, get_tag(), "----- Valid engine");
436         SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine uuid : %s", temp->engine_uuid);
437         SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine name : %s", temp->engine_name);
438         SECURE_SLOG(LOG_DEBUG, get_tag(), "Setting path : %s", temp->setting_ug_path);
439         SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine path : %s", temp->engine_path);
440         SECURE_SLOG(LOG_DEBUG, get_tag(), "Use network : %s", temp->use_network ? "true":"false");
441         SLOG(LOG_DEBUG, get_tag(), "-----");
442         SLOG(LOG_DEBUG, get_tag(), "  ");
443
444         *info = temp;
445
446         return 0;
447 }
448
449 int __internal_update_engine_list()
450 {
451         /* relsease engine list */
452         GList *iter = NULL;
453         ttsengine_info_s *data = NULL;
454
455         if (g_list_length(g_engine_list) > 0) {
456                 iter = g_list_first(g_engine_list);
457
458                 while (NULL != iter) {
459                         data = iter->data;
460
461                         if (data != NULL)       free(data);
462                         g_engine_list = g_list_remove_link(g_engine_list, iter);
463                         iter = g_list_first(g_engine_list);
464                 }
465         }
466
467         /* get file name from engine directory and get engine information from each filename */
468         DIR *dp;
469         struct dirent *dirp;
470         dp = opendir(TTS_DEFAULT_ENGINE);
471
472         if (dp != NULL) {
473                 while ((dirp = readdir(dp)) != NULL) {
474                         ttsengine_info_s* info;
475                         char* filepath = NULL;
476                         int file_size;
477
478                         file_size = strlen(TTS_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
479                         filepath = (char*)calloc(file_size, sizeof(char));
480
481                         if (NULL != filepath) { 
482                                 snprintf(filepath, file_size, "%s/%s", TTS_DEFAULT_ENGINE, dirp->d_name);
483                         } else {
484                                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not enough memory!!" );
485                                 continue;       
486                         }
487
488                         /* get its info and update engine list */
489                         if (0 == __internal_get_engine_info(filepath, &info)) {
490                                 /* add engine info to g_engine_list */
491                                 g_engine_list = g_list_append(g_engine_list, info);
492                         }
493
494                         if (NULL != filepath)   free(filepath);
495                 }
496
497                 closedir(dp);
498         }
499
500         dp = opendir(TTS_DOWNLOAD_ENGINE);
501
502         if (dp != NULL) {
503                 while ((dirp = readdir(dp)) != NULL) {
504                         ttsengine_info_s* info;
505                         char* filepath = NULL;
506                         int file_size;
507
508                         file_size = strlen(TTS_DOWNLOAD_ENGINE) + strlen(dirp->d_name) + 5;
509                         filepath = (char*)calloc(file_size, sizeof(char));
510
511                         if (NULL != filepath) {
512                                 snprintf(filepath, file_size, "%s/%s", TTS_DOWNLOAD_ENGINE, dirp->d_name);
513                         } else {
514                                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not enough memory!!" );
515                                 continue;       
516                         }
517
518                         /* get its info and update engine list */
519                         if (0 == __internal_get_engine_info(filepath, &info)) {
520                                 /* add engine info to g_engine_list */
521                                 g_engine_list = g_list_append(g_engine_list, info);
522                         }
523
524                         if (NULL != filepath)   free(filepath);
525                 }
526
527                 closedir(dp);
528         }
529
530         if (g_list_length(g_engine_list) <= 0) {
531                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Engine");
532                 return TTSD_ERROR_OPERATION_FAILED;     
533         }
534
535 #ifdef ENGINE_AGENT_DEBUG
536         ttsd_print_enginelist();
537 #endif
538         return 0;
539 }
540
541 int __internal_set_current_engine(const char* engine_uuid)
542 {
543         /* check whether engine id is valid or not. */
544         GList *iter = NULL;
545         ttsengine_info_s *data = NULL;
546
547         bool flag = false;
548         if (g_list_length(g_engine_list) > 0) {
549                 iter = g_list_first(g_engine_list);
550
551                 while (NULL != iter) {
552                         data = iter->data;
553
554                         if (0 == strncmp(data->engine_uuid, engine_uuid, strlen(engine_uuid))) {
555                                 flag = true;
556                                 break;
557                         }
558
559                         /*Get next item*/
560                         iter = g_list_next(iter);
561                 }
562         }
563
564         /* If current engine does not exist, return error */
565         if (false == flag) {
566                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Cannot find engine id");
567                 return TTSD_ERROR_OPERATION_FAILED;
568         } else {
569                 if (g_cur_engine.engine_uuid != NULL) {
570                         /*compare current engine uuid */
571                         if (0 == strncmp(g_cur_engine.engine_uuid, data->engine_uuid, strlen(engine_uuid))) {
572                                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] tts engine has already been set");
573                                 return 0;
574                         }
575                 }
576         }
577
578         /* set data from g_engine_list */
579         if (g_cur_engine.engine_uuid != NULL)   free(g_cur_engine.engine_uuid);
580         if (g_cur_engine.engine_name != NULL)   free(g_cur_engine.engine_name);
581         if (g_cur_engine.engine_path != NULL)   free(g_cur_engine.engine_path);
582
583         if (NULL == data->engine_uuid || NULL == data->engine_name || NULL == data->engine_path) {
584                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Engine data is NULL");
585                 return TTSD_ERROR_OPERATION_FAILED;
586         }
587
588         g_cur_engine.engine_uuid = strdup(data->engine_uuid);
589         g_cur_engine.engine_name = strdup(data->engine_name);
590         g_cur_engine.engine_path = strdup(data->engine_path);
591
592         g_cur_engine.handle = NULL;
593         g_cur_engine.is_loaded = false;
594         g_cur_engine.is_set = true;
595         g_cur_engine.need_network = data->use_network;
596
597         SLOG(LOG_DEBUG, get_tag(), "-----");
598         SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine uuid : %s", g_cur_engine.engine_uuid);
599         SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine name : %s", g_cur_engine.engine_name);
600         SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine path : %s", g_cur_engine.engine_path);
601         SLOG(LOG_DEBUG, get_tag(), "-----");
602
603         return 0;
604 }
605
606 bool __set_voice_info_cb(const char* language, int type, void* user_data)
607 {
608         if (NULL == language) {
609                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
610                 return false;
611         }
612
613         ttsvoice_s* voice = calloc(1, sizeof(ttsvoice_s));
614         voice->lang = strdup(language);
615         voice->type = type;
616
617         voice->client_ref_count = 0;
618         voice->is_loaded = false;
619
620         if (0 == strcmp(g_cur_engine.default_lang, language) && g_cur_engine.default_vctype == type) {
621                 voice->is_default = true;
622                 voice->is_loaded = true;
623         } else {
624                 voice->is_default = false;
625         }
626
627         g_cur_voices = g_slist_append(g_cur_voices, voice);
628
629         return true;
630 }
631
632 int __update_voice_list()
633 {
634         /* Get voice list */
635         g_cur_voices = NULL;
636         int ret = 0;
637
638         ret = g_cur_engine.pefuncs->foreach_voices(__set_voice_info_cb, NULL);
639         if (0 != ret || 0 >= g_slist_length(g_cur_voices)) {
640                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
641                 return -1;
642         }
643
644 #ifdef ENGINE_AGENT_DEBUG
645         ttsd_print_voicelist();
646 #endif
647         return 0;
648 }
649
650 int ttsd_engine_agent_load_current_engine()
651 {
652         if (false == g_agent_init) {
653                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
654                 return TTSD_ERROR_OPERATION_FAILED;
655         }
656
657         if (false == g_cur_engine.is_set) {
658                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Current Engine ");
659                 return TTSD_ERROR_OPERATION_FAILED;
660         }
661
662         /* check whether current engine is loaded or not */
663         if (true == g_cur_engine.is_loaded ) {
664                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent] Engine has already been loaded " );
665                 return 0;
666         }
667
668         /* open engine */
669         char *error = NULL;
670         g_cur_engine.handle = dlopen(g_cur_engine.engine_path, RTLD_LAZY); /* RTLD_LAZY RTLD_NOW*/
671
672         if (NULL != (error = dlerror()) || NULL == g_cur_engine.handle) {
673                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to get current engine handle : %s", error);
674                 return -2;
675         }
676
677         g_cur_engine.ttsp_unload_engine = (int (*)())dlsym(g_cur_engine.handle, "ttsp_unload_engine");
678         if (NULL != (error = dlerror()) || NULL == g_cur_engine.ttsp_unload_engine) {
679                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to link daemon to ttsp_unload_engine() : %s", error);
680                 return -3;
681         }
682
683         g_cur_engine.ttsp_load_engine = (int (*)(const ttspd_funcs_s* , ttspe_funcs_s*) )dlsym(g_cur_engine.handle, "ttsp_load_engine");
684         if (NULL != (error = dlerror()) || NULL == g_cur_engine.ttsp_load_engine) {
685                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to link daemon to ttsp_load_engine() : %s", error);
686                 return -3;
687         }
688
689         /* load engine */
690         g_cur_engine.pdfuncs->version = 1;
691         g_cur_engine.pdfuncs->size = sizeof(ttspd_funcs_s);
692
693         int ret = 0;
694         ret = g_cur_engine.ttsp_load_engine(g_cur_engine.pdfuncs, g_cur_engine.pefuncs); 
695         if (0 != ret) {
696                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to load engine - %s : result(%s)", 
697                         g_cur_engine.engine_path, __ttsd_get_engine_error_code(ret));
698                 return TTSD_ERROR_OPERATION_FAILED;
699         }
700
701         /* engine error check */
702         if (g_cur_engine.pefuncs->size != sizeof(ttspe_funcs_s)) {
703                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] The size of engine function is not valid");
704         }
705
706         if (NULL == g_cur_engine.pefuncs->initialize ||
707                 NULL == g_cur_engine.pefuncs->deinitialize ||
708                 NULL == g_cur_engine.pefuncs->foreach_voices ||
709                 NULL == g_cur_engine.pefuncs->is_valid_voice ||
710                 NULL == g_cur_engine.pefuncs->start_synth ||
711                 NULL == g_cur_engine.pefuncs->cancel_synth) {
712                 SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] The engine functions are NOT valid");
713                 return TTSD_ERROR_OPERATION_FAILED; 
714         }
715
716         ret = g_cur_engine.pefuncs->initialize(__result_cb);
717         if (0 != ret) {
718                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to initialize current engine : %s", __ttsd_get_engine_error_code(ret));
719                 return TTSD_ERROR_OPERATION_FAILED;
720         }
721
722         /* Get voice info of current engine */
723         ret = __update_voice_list();
724         if (0 != ret) {
725                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set voice info : result(%d)", ret);
726                 return TTSD_ERROR_OPERATION_FAILED;
727         }
728
729         /* Select default voice */
730         if (NULL != g_cur_engine.default_lang) {
731                 if (true == g_cur_engine.pefuncs->is_valid_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype)) {
732                         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set origin default voice to current engine : lang(%s), type(%d)", 
733                                 g_cur_engine.default_lang,  g_cur_engine.default_vctype);
734                 } else {
735                         SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Fail set origin default voice : lang(%s), type(%d)",
736                                 g_cur_engine.default_lang, g_cur_engine.default_vctype);
737
738                         return TTSD_ERROR_OPERATION_FAILED;
739                 }
740         }
741
742         /* load default voice */
743         if (NULL != g_cur_engine.pefuncs->load_voice) {
744                 ret = g_cur_engine.pefuncs->load_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype);
745                 if (0 == ret) {
746                         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Load default voice : lang(%s), type(%d)", 
747                                 g_cur_engine.default_lang,  g_cur_engine.default_vctype);
748                 } else {
749                         SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] Fail to load default voice : lang(%s), type(%d) result(%s)",
750                                 g_cur_engine.default_lang, g_cur_engine.default_vctype, __ttsd_get_engine_error_code(ret));
751
752                         return TTSD_ERROR_OPERATION_FAILED;
753                 }
754         }
755
756 #if 0
757         if (false == set_voice) {
758                 /* get language list */
759                 int ret;
760                 GList* voice_list = NULL;
761
762                 ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list);
763
764                 if (0 == ret && 0 < g_list_length(voice_list)) {
765                         GList *iter = NULL;
766                         voice_s* voice = NULL;
767                         
768                         iter = g_list_first(voice_list);
769
770                         /* check english */
771                         while (NULL != iter) {
772                                 voice = iter->data;
773
774                                 if (NULL != voice) {
775                                         if (0 == strcmp("en_US", voice->language)) 
776                                                 break;
777                                 }
778
779                                 iter = g_list_next(iter);
780                         }
781                         if (NULL == voice) {
782                                 SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail to find voice in list");
783                                 return TTSD_ERROR_OPERATION_FAILED;
784                         }
785         
786                         /* Set selected language and type */
787                         if (true != g_cur_engine.pefuncs->is_valid_voice(voice->language, voice->type)) {
788                                 SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail voice is NOT valid");
789                                 return TTSD_ERROR_OPERATION_FAILED;
790                         }
791
792                         ttsd_config_set_default_voice(voice->language, (int)voice->type);
793                         
794                         g_cur_engine.default_lang = strdup(voice->language);
795                         g_cur_engine.default_vctype = voice->type;
796
797                         SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Select default voice : lang(%s), type(%d)", 
798                                 voice->language,  voice->type);
799
800                         __free_voice_list(voice_list);
801                 } else {
802                         SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail to get language list : result(%d)", ret);
803                         return TTSD_ERROR_OPERATION_FAILED;
804                 }
805         }
806 #endif
807         g_cur_engine.is_loaded = true;
808
809         return 0;
810 }
811
812 int ttsd_engine_agent_unload_current_engine()
813 {
814         if (false == g_agent_init) {
815                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
816                 return TTSD_ERROR_OPERATION_FAILED;
817         }
818
819         if (false == g_cur_engine.is_set) {
820                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Current Engine ");
821                 return TTSD_ERROR_OPERATION_FAILED;
822         }
823
824         if (false == g_cur_engine.is_loaded) {
825                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Engine has already been unloaded " );
826                 return 0;
827         }
828
829         /* shutdown engine */
830         int ret = 0;
831         ret = g_cur_engine.pefuncs->deinitialize();
832         if (0 != ret) {
833                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent] Fail deinitialize() : %s", __ttsd_get_engine_error_code(ret));
834         }
835
836         /* unload engine */
837         g_cur_engine.ttsp_unload_engine();
838         
839         dlclose(g_cur_engine.handle);
840
841         /* reset current engine data */
842         g_cur_engine.handle = NULL;
843         g_cur_engine.is_loaded = false;
844
845         GSList *iter = NULL;
846         ttsvoice_s* data = NULL;
847
848         iter = g_slist_nth(g_cur_voices, 0);
849         while (NULL != iter) {
850                 data = iter->data;
851
852                 if (NULL != data) {
853                         if (NULL != data->lang)         free(data->lang);
854                         g_cur_voices = g_slist_remove(g_cur_voices, data);
855                         free(data);
856                         data = NULL;
857                 }
858
859                 iter = g_slist_nth(g_cur_voices, 0);
860         }
861
862         return 0;
863 }
864
865 bool ttsd_engine_agent_need_network()
866 {
867         if (false == g_agent_init) {
868                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
869                 return TTSD_ERROR_OPERATION_FAILED;
870         }
871
872         if (false == g_cur_engine.is_loaded) {
873                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
874                 return TTSD_ERROR_OPERATION_FAILED;
875         }
876
877         return g_cur_engine.need_network;
878 }
879
880 bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, int* out_type)
881 {
882         if (NULL == lang || NULL == out_lang || NULL == out_type) {
883                 return false;
884         }
885
886         if (false == g_cur_engine.is_loaded) {
887                 SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Not loaded engine");
888                 return false;
889         }
890
891         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Select voice : input lang(%s), input type(%d), default lang(%s), default type(%d)", 
892                 lang, type, g_cur_engine.default_lang, g_cur_engine.default_vctype);
893
894         
895         /* case 1 : Both are default */
896         if (0 == strncmp(lang, "default", strlen("default")) && 0 == type) {
897                 *out_lang = strdup(g_cur_engine.default_lang);
898                 *out_type = g_cur_engine.default_vctype;
899                 return true;
900         }
901         
902         /* Get voice list */
903         GList* voice_list = NULL;
904         int ret = 0;
905
906         ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list);
907         if (0 != ret || 0 >= g_list_length(voice_list)) {
908                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
909                 return false;
910         }
911
912         bool result;
913         result = false;
914
915         GList *iter = NULL;
916         voice_s* voice;
917
918         /* lang and type are not default type */
919         if (0 != strncmp(lang, "default", strlen("default")) && 0 != type) {
920                 iter = g_list_first(voice_list);
921
922                 while (NULL != iter) {
923                         /* Get handle data from list */
924                         voice = iter->data;
925
926                         if (0 == strncmp(voice->language, lang, strlen(lang)) &&  voice->type == type) {
927                                 *out_lang = strdup(voice->language);
928                                 *out_type = voice->type;
929                                 result = true;
930                                 break;
931                         }
932
933                         iter = g_list_next(iter);
934                 }
935
936         } else if (0 != strncmp(lang, "default", strlen("default")) && 0 == type) {
937                 /* Only type is default */
938                 if (0 == strncmp(lang, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang))) {
939                         *out_lang = strdup(g_cur_engine.default_lang);
940                         *out_type = g_cur_engine.default_vctype;
941                         result = true;
942                 } else {
943                         voice_s* voice_selected = NULL;
944                         iter = g_list_first(voice_list);
945                         while (NULL != iter) {
946                                 /* Get handle data from list */
947                                 voice = iter->data;
948
949                                 if (0 == strncmp(voice->language, lang, strlen(lang))) {
950                                         voice_selected = voice;
951                                         if (voice->type == g_cur_engine.default_vctype) {
952                                                 voice_selected = voice;
953                                                 break;
954                                         }
955                                 }
956                                 iter = g_list_next(iter);
957                         }
958
959                         if (NULL != voice_selected) {
960                                 *out_lang = strdup(voice_selected->language);
961                                 *out_type = voice_selected->type;
962                                 result = true;
963                         }
964                 }
965         } else if (0 == strncmp(lang, "default", strlen("default")) && 0 != type) {
966                 /* Only lang is default */
967                 if (type == g_cur_engine.default_vctype) {
968                         *out_lang = strdup(g_cur_engine.default_lang);
969                         *out_type = g_cur_engine.default_vctype;
970                         result = true;
971                 } else {
972                         voice_s* voice_selected = NULL;
973                         iter = g_list_first(voice_list);
974                         while (NULL != iter) {
975                                 /* Get handle data from list */
976                                 voice = iter->data;
977
978                                 if (0 == strncmp(voice->language, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang)) ) {
979                                         voice_selected = voice;
980                                         if (voice->type == type) {
981                                                 voice_selected = voice;
982                                                 break;
983                                         }
984                                 }
985                                 iter = g_list_next(iter);
986                         }
987
988                         if (NULL != voice_selected) {
989                                 *out_lang = strdup(voice->language);
990                                 *out_type = voice_selected->type;
991                                 result = true;
992                         }
993                 }
994         }
995
996         if (true == result) {
997                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Selected voice : lang(%s), type(%d)", *out_lang, *out_type);
998         }
999
1000         __free_voice_list(voice_list);
1001
1002         return result;
1003 }
1004
1005 bool ttsd_engine_agent_is_same_engine(const char* engine_id)
1006 {
1007         if (false == g_agent_init) {
1008                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1009                 return false;
1010         }
1011
1012         if (false == g_cur_engine.is_loaded) {
1013                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1014                 return false;
1015         }
1016
1017         /* compare current engine and engine id.*/
1018         if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) {
1019                 return true;
1020         }
1021
1022         return false;
1023 }
1024
1025 int ttsd_engine_agent_set_default_engine(const char* engine_id)
1026 {
1027         if (false == g_agent_init) {
1028                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1029                 return TTSD_ERROR_OPERATION_FAILED;
1030         }
1031
1032         /* compare current engine and new engine.*/
1033         if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) {
1034                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] new engine(%s) is the same as current engine", engine_id);
1035                 return 0;
1036         }
1037
1038         bool is_engine_loaded = false; 
1039         char* tmp_uuid = NULL;
1040         tmp_uuid = strdup(g_cur_engine.engine_uuid);
1041         if (NULL == tmp_uuid) {
1042                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Current engine id is NULL");
1043                         return TTSD_ERROR_OPERATION_FAILED;
1044         }
1045
1046         is_engine_loaded = g_cur_engine.is_loaded;
1047
1048         if (true == is_engine_loaded) {
1049                 /* unload engine */
1050                 if (0 != ttsd_engine_agent_unload_current_engine()) {
1051                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent Error] fail to unload current engine");
1052                 }
1053         }
1054
1055         /* change current engine */
1056         if (0 != __internal_set_current_engine(engine_id)) {
1057                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set current engine. Recovery origin engine");
1058
1059                 /* roll back to old current engine. */
1060                 __internal_set_current_engine(tmp_uuid);
1061                 if (true == is_engine_loaded) {
1062                         ttsd_engine_agent_load_current_engine();
1063                 }
1064                 
1065                 if (tmp_uuid != NULL)   free(tmp_uuid);
1066                 return TTSD_ERROR_OPERATION_FAILED;
1067         }
1068
1069         if (true == is_engine_loaded) {
1070                 /* load engine */
1071                 if (0 != ttsd_engine_agent_load_current_engine()) {
1072                         SLOG(LOG_ERROR, get_tag(), "[Engine Agent Error] Fail to load new engine. Recovery origin engine");
1073                         
1074                         /* roll back to old current engine. */
1075                         __internal_set_current_engine(tmp_uuid);
1076                         if (true == is_engine_loaded) {
1077                                 ttsd_engine_agent_load_current_engine();
1078                         }
1079
1080                         if (tmp_uuid != NULL)   free(tmp_uuid);
1081                         return TTSD_ERROR_OPERATION_FAILED;
1082                 } else {
1083                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] load new engine : %s", engine_id);
1084                 }
1085         }
1086
1087         if (tmp_uuid != NULL)   free(tmp_uuid);
1088         return 0;
1089 }
1090
1091 int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
1092 {
1093         if (false == g_agent_init) {
1094                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1095                 return TTSD_ERROR_OPERATION_FAILED;
1096         }
1097
1098         if (false == g_cur_engine.is_loaded) {
1099                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1100                 return TTSD_ERROR_OPERATION_FAILED;
1101         }
1102
1103         if (false == g_cur_engine.pefuncs->is_valid_voice(language, vctype)) {
1104                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice is NOT valid !!");
1105                 return TTSD_ERROR_INVALID_VOICE;
1106         }
1107
1108         int ret = -1;
1109         GSList *iter = NULL;
1110         ttsvoice_s* data = NULL;
1111
1112         /* Update new default voice info */
1113         iter = g_slist_nth(g_cur_voices, 0);
1114         while (NULL != iter) {
1115                 /* Get handle data from list */
1116                 data = iter->data;
1117
1118                 if (NULL == data) {
1119                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice data is NULL");
1120                         return TTSD_ERROR_OPERATION_FAILED;
1121                 }
1122
1123                 if (0 == strcmp(data->lang, language) && data->type == vctype) {
1124                         data->is_default = true;
1125                         if (0 == data->client_ref_count) {
1126                                 /* load voice */
1127                                 if (NULL != g_cur_engine.pefuncs->load_voice) {
1128                                         ret = g_cur_engine.pefuncs->load_voice(data->lang, data->type);
1129                                         if (0 == ret) {
1130                                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] load voice : lang(%s), type(%d)", 
1131                                                         data->lang, data->type);
1132                                                 data->is_loaded = true;
1133                                         } else {
1134                                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
1135                                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1136                                         }
1137                                 } else {
1138                                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Load voice of engine function is NULL");
1139                                 }
1140                         }
1141                         break;
1142                 }
1143                 
1144                 /*Get next item*/
1145                 iter = g_slist_next(iter);
1146         }
1147
1148 #ifdef ENGINE_AGENT_DEBUG
1149         ttsd_print_voicelist();
1150 #endif
1151
1152         /* Update old default voice info */
1153         iter = g_slist_nth(g_cur_voices, 0);
1154         while (NULL != iter) {
1155                 /*Get handle data from list*/
1156                 data = iter->data;
1157
1158                 if (NULL == data) {
1159                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice data is NULL");
1160                         return TTSD_ERROR_OPERATION_FAILED;
1161                 }
1162
1163                 if (0 == strcmp(data->lang, g_cur_engine.default_lang) && data->type == g_cur_engine.default_vctype) {
1164                         data->is_default = false;
1165                         if (0 == data->client_ref_count) {
1166                                 /* Unload voice */
1167                                 if (NULL != g_cur_engine.pefuncs->unload_voice) {
1168                                         ret = g_cur_engine.pefuncs->unload_voice(data->lang, data->type);
1169                                         if (0 == ret) {
1170                                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
1171                                                         data->lang, data->type);
1172                                                 data->is_loaded = false;
1173                                         } else {
1174                                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
1175                                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1176                                         }
1177                                 } else {
1178                                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Unload voice of engine function is NULL");
1179                                 }
1180                         }
1181                         break;
1182                 }
1183                 
1184                 /*Get next item*/
1185                 iter = g_slist_next(iter);
1186         }
1187
1188         if (NULL != g_cur_engine.default_lang)  free(g_cur_engine.default_lang);
1189
1190         g_cur_engine.default_lang = strdup(language);
1191         g_cur_engine.default_vctype = vctype;
1192
1193 #ifdef ENGINE_AGENT_DEBUG
1194         ttsd_print_voicelist();
1195 #endif
1196
1197         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set default voice : lang(%s), type(%d)",
1198                 g_cur_engine.default_lang, g_cur_engine.default_vctype);
1199
1200         return 0;
1201 }
1202
1203 int ttsd_engine_agent_set_default_speed(int speed)
1204 {
1205         if (false == g_agent_init) {
1206                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1207                 return TTSD_ERROR_OPERATION_FAILED;
1208         }
1209
1210         g_cur_engine.default_speed = speed;
1211
1212         return 0;
1213 }
1214
1215 int ttsd_engine_agent_set_default_pitch(int pitch)
1216 {
1217         if (false == g_agent_init) {
1218                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1219                 return TTSD_ERROR_OPERATION_FAILED;
1220         }
1221
1222         if (false == g_cur_engine.is_loaded) {
1223                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1224                 return TTSD_ERROR_OPERATION_FAILED;
1225         }
1226
1227         if (NULL == g_cur_engine.pefuncs->set_pitch) {
1228                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not support pitch");
1229                 return TTSD_ERROR_OPERATION_FAILED;
1230         }
1231
1232         int ret = g_cur_engine.pefuncs->set_pitch(pitch);
1233         if (0 != ret) {
1234                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)", 
1235                         pitch, __ttsd_get_engine_error_code(ret));
1236                 return TTSD_ERROR_OPERATION_FAILED;
1237         }
1238
1239         g_cur_engine.default_pitch = pitch;
1240
1241         return 0;
1242 }
1243
1244 /******************************************************************************************
1245 * TTS Engine Interfaces for client
1246 *******************************************************************************************/
1247
1248 int ttsd_engine_load_voice(const char* lang, const int vctype)
1249 {
1250         /* 1. Find voice info */
1251         int ret = -1;
1252         GSList *iter = NULL;
1253         ttsvoice_s* data = NULL;
1254
1255         iter = g_slist_nth(g_cur_voices, 0);
1256         while (NULL != iter) {
1257                 /*Get handle data from list*/
1258                 data = iter->data;
1259
1260                 if (NULL != data) {
1261                         if (0 == strcmp(data->lang, lang) && data->type == vctype) {
1262                                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)", 
1263                                         data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
1264                                 break;
1265                         }
1266                 }
1267                 
1268                 /*Get next item*/
1269                 iter = g_slist_next(iter);
1270                 data = NULL;
1271         }
1272
1273         if (NULL == data) {
1274                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
1275                 return TTSD_ERROR_OPERATION_FAILED;
1276         }
1277
1278         /* 2. increse ref count */
1279         data->client_ref_count++;
1280
1281         /* 3. if ref count change 0 to 1 and not default, load voice */
1282         if (1 == data->client_ref_count && false == data->is_default) {
1283                 /* load voice */
1284                 if (NULL != g_cur_engine.pefuncs->load_voice) {
1285                         ret = g_cur_engine.pefuncs->load_voice(data->lang, data->type);
1286                         if (0 == ret) {
1287                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Load voice : lang(%s), type(%d)", 
1288                                         data->lang, data->type);
1289                                 data->is_loaded = true;
1290                         } else {
1291                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
1292                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1293
1294                                 return TTSD_ERROR_OPERATION_FAILED;
1295                         }
1296                 } else {
1297                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Load voice of engine function is NULL");
1298                 }
1299         } else {
1300                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Not load voice : default voice(%d) or ref count(%d)",
1301                         data->is_default, data->client_ref_count);
1302         }
1303
1304 #ifdef ENGINE_AGENT_DEBUG
1305         ttsd_print_voicelist();
1306 #endif
1307
1308         return 0;
1309 }
1310
1311 int ttsd_engine_unload_voice(const char* lang, const int vctype)
1312 {
1313         /* 1. Find voice info */
1314         int ret = -1;
1315         GSList *iter = NULL;
1316         ttsvoice_s* data = NULL;
1317
1318         iter = g_slist_nth(g_cur_voices, 0);
1319         while (NULL != iter) {
1320                 /*Get handle data from list*/
1321                 data = iter->data;
1322
1323                 if (NULL != data) {
1324                         if (0 == strcmp(data->lang, lang) && data->type == vctype) {
1325                                 SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)", 
1326                                         data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
1327                                 break;
1328                         }
1329                 }
1330                 
1331                 /*Get next item*/
1332                 iter = g_slist_next(iter);
1333                 data = NULL;
1334         }
1335
1336         if (NULL == data) {
1337                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
1338                 return TTSD_ERROR_OPERATION_FAILED;
1339         }
1340
1341         /* 2. Decrese ref count */
1342         data->client_ref_count--;
1343
1344         /* 3. if ref count change 0 and not default, load voice */
1345         if (0 == data->client_ref_count && false == data->is_default) {
1346                 /* load voice */
1347                 if (NULL != g_cur_engine.pefuncs->unload_voice) {
1348                         ret = g_cur_engine.pefuncs->unload_voice(data->lang, data->type);
1349                         if (0 == ret) {
1350                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
1351                                         data->lang, data->type);
1352                                 data->is_loaded = false;
1353                         } else {
1354                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
1355                                         data->lang, data->type, __ttsd_get_engine_error_code(ret));
1356
1357                                 return TTSD_ERROR_OPERATION_FAILED;
1358                         }
1359                 } else {
1360                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Unload voice of engine function is NULL");
1361                 }
1362         } else {
1363                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Not unload voice : default voice(%d) or ref count(%d)",
1364                         data->is_default, data->client_ref_count);
1365         }
1366
1367 #ifdef ENGINE_AGENT_DEBUG
1368         ttsd_print_voicelist();
1369 #endif
1370         return 0;
1371 }
1372
1373 int ttsd_engine_start_synthesis(const char* lang, int vctype, const char* text, int speed, void* user_param)
1374 {
1375         if (false == g_agent_init) {
1376                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1377                 return TTSD_ERROR_OPERATION_FAILED;
1378         }
1379
1380         if (false == g_cur_engine.is_loaded) {
1381                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1382                 return TTSD_ERROR_OPERATION_FAILED;
1383         }
1384
1385         /* select voice for default */
1386         char* temp_lang = NULL;
1387         int temp_type;
1388         if (true != ttsd_engine_select_valid_voice(lang, vctype, &temp_lang, &temp_type)) {
1389                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to select default voice");
1390                 if (NULL != temp_lang)  free(temp_lang);
1391                 return TTSD_ERROR_INVALID_VOICE;
1392         } else {
1393                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Start synthesis : language(%s), type(%d), speed(%d), text(%s)", 
1394                         temp_lang, temp_type, speed, text);
1395         }
1396
1397         if (NULL == g_cur_engine.pefuncs->start_synth) {
1398                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] start_synth() of engine is NULL!!");
1399                 if (NULL != temp_lang)  free(temp_lang);
1400                 return TTSD_ERROR_OPERATION_FAILED;
1401         }
1402
1403         int temp_speed;
1404
1405         if (0 == speed) {
1406                 temp_speed = g_cur_engine.default_speed;
1407         } else {
1408                 temp_speed = speed;
1409         }
1410
1411         /* synthesize text */
1412         int ret = 0;
1413         ret = g_cur_engine.pefuncs->start_synth(temp_lang, temp_type, text, temp_speed, user_param);
1414         if (0 != ret) {
1415                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] ***************************************");
1416                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] * synthesize error : %s *", __ttsd_get_engine_error_code(ret));
1417                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] ***************************************");
1418                 if (NULL != temp_lang)  free(temp_lang);
1419                 return TTSD_ERROR_OPERATION_FAILED;
1420         }
1421
1422         if (NULL != temp_lang)  free(temp_lang);
1423         return 0;
1424 }
1425
1426 int ttsd_engine_cancel_synthesis()
1427 {
1428         if (false == g_agent_init) {
1429                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1430                 return TTSD_ERROR_OPERATION_FAILED;
1431         }
1432
1433         if (false == g_cur_engine.is_loaded) {
1434                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1435                 return TTSD_ERROR_OPERATION_FAILED;
1436         }
1437         
1438         if (NULL == g_cur_engine.pefuncs->cancel_synth) {
1439                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] cancel_synth() of engine is NULL!!");
1440                 return TTSD_ERROR_OPERATION_FAILED;
1441         }
1442
1443         /* stop synthesis */
1444         int ret = 0;
1445         ret = g_cur_engine.pefuncs->cancel_synth();
1446         if (0 != ret) {
1447                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail cancel synthesis : %s", __ttsd_get_engine_error_code(ret));
1448                 return TTSD_ERROR_OPERATION_FAILED;
1449         }
1450
1451         return 0;
1452 }
1453
1454 bool __supported_voice_cb(const char* language, int type, void* user_data)
1455 {
1456         GList** voice_list = (GList**)user_data;
1457
1458         if (NULL == language || NULL == voice_list) {
1459                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
1460                 return false;
1461         }
1462
1463         voice_s* voice = calloc(1, sizeof(voice_s));
1464         voice->language = strdup(language);
1465         voice->type = type;
1466
1467         *voice_list = g_list_append(*voice_list, voice);
1468
1469         return true;
1470 }
1471
1472 int ttsd_engine_get_voice_list(GList** voice_list)
1473 {
1474         if (false == g_agent_init) {
1475                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1476                 return TTSD_ERROR_OPERATION_FAILED;
1477         }
1478
1479         if (false == g_cur_engine.is_loaded) {
1480                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1481                 return TTSD_ERROR_OPERATION_FAILED;
1482         }
1483
1484         int ret = 0;
1485         ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, (void*)voice_list);
1486         if (0 != ret) {
1487                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to get voice list : %s", __ttsd_get_engine_error_code(ret));
1488                 return TTSD_ERROR_OPERATION_FAILED;
1489         }
1490
1491         return 0;
1492 }
1493
1494 int ttsd_engine_get_default_voice(char** lang, int* vctype)
1495 {
1496         if (false == g_agent_init) {
1497                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized" );
1498                 return TTSD_ERROR_OPERATION_FAILED;
1499         }
1500
1501         if (false == g_cur_engine.is_loaded) {
1502                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
1503                 return TTSD_ERROR_OPERATION_FAILED;
1504         }
1505
1506         if (NULL == lang || NULL == vctype) {
1507                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] BAD Parameter"); 
1508                 return TTSD_ERROR_INVALID_PARAMETER;
1509         }
1510
1511         if (NULL != g_cur_engine.default_lang) {
1512                 *lang = strdup(g_cur_engine.default_lang);
1513                 *vctype = g_cur_engine.default_vctype;
1514
1515                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine] Get default voice : language(%s), type(%d)", *lang, *vctype);
1516         } else {
1517                 SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Default voice is NULL");
1518                 return TTSD_ERROR_OPERATION_FAILED;
1519         }
1520         
1521         return 0;
1522 }
1523
1524 void __free_voice_list(GList* voice_list)
1525 {
1526         GList *iter = NULL;
1527         voice_s* data = NULL;
1528
1529         /* if list have item */
1530         if (g_list_length(voice_list) > 0) {
1531                 /* Get a first item */
1532                 iter = g_list_first(voice_list);
1533
1534                 while (NULL != iter) {
1535                         data = iter->data;
1536                         
1537                         if (NULL != data) {
1538                                 if (NULL != data->language)     free(data->language);
1539                                 free(data);
1540                         }
1541                         
1542                         voice_list = g_list_remove_link(voice_list, iter);
1543                         
1544                         iter = g_list_first(voice_list);
1545                 }
1546         }
1547 }
1548
1549 /*
1550 * TTS Engine Callback Functions                                                                                 `                                 *
1551 */
1552 bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, ttsp_audio_type_e audio_type, int rate, void *user_data)
1553 {
1554         g_result_cb(event, data, data_size, audio_type, rate, user_data);
1555         return true;
1556 }
1557
1558 /* function for debugging */
1559 int ttsd_print_enginelist()
1560 {
1561         GList *iter = NULL;
1562         ttsengine_info_s *data = NULL;
1563
1564         if (g_list_length(g_engine_list) > 0) {
1565                 iter = g_list_first(g_engine_list);
1566
1567                 SLOG(LOG_DEBUG, get_tag(), "----- engine list -----");
1568
1569                 int i = 1;      
1570                 while (NULL != iter) {
1571                         data = iter->data;
1572
1573                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[%dth]", i);
1574                         SECURE_SLOG(LOG_DEBUG, get_tag(), "engine uuid : %s", data->engine_uuid);
1575                         SECURE_SLOG(LOG_DEBUG, get_tag(), "engine name : %s", data->engine_name);
1576                         SECURE_SLOG(LOG_DEBUG, get_tag(), "engine path : %s", data->engine_path);
1577                         SECURE_SLOG(LOG_DEBUG, get_tag(), "setting ug path : %s", data->setting_ug_path);
1578
1579                         iter = g_list_next(iter);
1580                         i++;
1581                 }
1582                 SLOG(LOG_DEBUG, get_tag(), "-----------------------");
1583                 SLOG(LOG_DEBUG, get_tag(), "  ");
1584         } else {
1585                 SLOG(LOG_DEBUG, get_tag(), "----- engine list -----");
1586                 SLOG(LOG_DEBUG, get_tag(), "No Engine in directory");
1587                 SLOG(LOG_DEBUG, get_tag(), "-----------------------");
1588         }
1589
1590         return 0;
1591 }
1592
1593 int ttsd_print_voicelist()
1594 {
1595         /* Test log */
1596         GSList *iter = NULL;
1597         ttsvoice_s* data = NULL;
1598
1599         SLOG(LOG_DEBUG, get_tag(), "=== Voice list ===");
1600
1601         if (g_slist_length(g_cur_voices) > 0) {
1602                 /* Get a first item */
1603                 iter = g_slist_nth(g_cur_voices, 0);
1604
1605                 int i = 1;      
1606                 while (NULL != iter) {
1607                         /*Get handle data from list*/
1608                         data = iter->data;
1609
1610                         if (NULL == data || NULL == data->lang) {
1611                                 SLOG(LOG_ERROR, get_tag(), "[ERROR] Data is invalid");
1612                                 return 0;
1613                         }
1614
1615                         SLOG(LOG_DEBUG, get_tag(), "[%dth] default(%d) loaded(%d) ref(%d) lang(%s) type(%d)", 
1616                                 i, data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
1617                         
1618                         /*Get next item*/
1619                         iter = g_slist_next(iter);
1620                         i++;
1621                 }
1622         }
1623
1624         SLOG(LOG_DEBUG, get_tag(), "==================");
1625
1626         return 0;
1627 }