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