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