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