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