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