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