Merge "Match the function hierarchy" into tizen
[platform/core/uifw/tts.git] / common / tts_config_parser.c
1 /*
2 *  Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved 
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14 #include <dlog.h>
15 #include <stdio.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <vconf.h>
19
20 #include "tts_config_parser.h"
21 #include "tts_defs.h"
22
23
24 #define TTS_TAG_ENGINE_BASE_TAG         "tts-engine"
25 #define TTS_TAG_ENGINE_NAME             "name"
26 #define TTS_TAG_ENGINE_ID               "id"
27 #define TTS_TAG_ENGINE_SETTING          "setting"
28 #define TTS_TAG_ENGINE_VOICE_SET        "voices"
29 #define TTS_TAG_ENGINE_VOICE            "voice"
30 #define TTS_TAG_ENGINE_VOICE_TYPE       "type"
31 #define TTS_TAG_ENGINE_PITCH_SUPPORT    "pitch-support"
32 #define TTS_TAG_ENGINE_TEXT_SIZE        "text-size"
33
34 #define TTS_TAG_CONFIG_BASE_TAG         "tts-config"
35 #define TTS_TAG_CONFIG_ENGINE_ID        "engine"
36 #define TTS_TAG_CONFIG_ENGINE_SETTING   "engine-setting"
37 #define TTS_TAG_CONFIG_AUTO_VOICE       "auto"
38 #define TTS_TAG_CONFIG_VOICE_TYPE       "voice-type"
39 #define TTS_TAG_CONFIG_LANGUAGE         "language"
40 #define TTS_TAG_CONFIG_SPEECH_RATE      "speech-rate"
41 #define TTS_TAG_CONFIG_PITCH            "pitch"
42 #define TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO          "background-volume-ratio"
43 #define TTS_TAG_VOICE_TYPE_FEMALE       "female"
44 #define TTS_TAG_VOICE_TYPE_MALE         "male"
45 #define TTS_TAG_VOICE_TYPE_CHILD        "child"
46
47 #define TTS_MAX_TEXT_SIZE       2000
48
49 static xmlDocPtr g_config_doc = NULL;
50 char g_engine_id[128] = {0,};
51 char g_setting[128] = {0,};
52 char g_language[128] = {0,};
53
54 int tts_parser_get_engine_info(const char* path, tts_engine_info_s** engine_info)
55 {
56         if (NULL == path || NULL == engine_info) {
57                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
58                 return -1;
59         }
60
61         // Avoid to parse non-xml file
62         char* file_ext = strrchr(path, '.');
63         if (NULL == ++file_ext || (file_ext && 0 != strncmp("xml", file_ext, strlen(file_ext)))) {
64                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] File extention is not XML type, file_ext(%s)", (file_ext) ? file_ext : "NULL");
65                 return -1;
66         }
67
68         bool isTextsize = false;
69         xmlDocPtr doc = NULL;
70         xmlNodePtr cur = NULL;
71         xmlChar *key = NULL;
72         xmlChar *attr = NULL;
73
74         if (0 == access(path, F_OK)) {
75                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", path);
76                 doc = xmlParseFile(path);
77                 if (doc == NULL) {
78                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse xml file");
79                         return -1;
80                 }
81         } else {
82                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", path);
83                 return -1;
84         }
85
86         cur = xmlDocGetRootElement(doc);
87         if (cur == NULL) {
88                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document. doc path(%s, %p)", path, doc);
89                 xmlFreeDoc(doc);
90                 doc = NULL;
91                 return -1;
92         }
93
94         if (xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_BASE_TAG)) {
95                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT 'tts-engine'. doc path(%s, %p)", path, doc);
96                 xmlFreeDoc(doc);
97                 doc = NULL;
98                 return -1;
99         }
100
101         cur = cur->xmlChildrenNode;
102         if (cur == NULL) {
103                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document. doc path(%s, %p)", path, doc);
104                 xmlFreeDoc(doc);
105                 doc = NULL;
106                 return -1;
107         }
108
109         /* alloc engine info */
110         tts_engine_info_s* temp;
111         temp = (tts_engine_info_s*)calloc(1, sizeof(tts_engine_info_s));
112         if (NULL == temp) {
113                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory. doc path(%s, %p)", path, doc);
114                 xmlFreeDoc(doc);
115                 doc = NULL;
116                 return -1;
117         }
118
119         temp->name = NULL;
120         temp->uuid = NULL;
121         temp->voices = NULL;
122         temp->setting = NULL;
123         temp->pitch_support = false;
124         temp->text_size = 0;
125
126         while (cur != NULL) {
127                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_NAME)) {
128                         key = xmlNodeGetContent(cur);
129                         if (NULL != key) {
130                                 if (NULL != temp->name) {
131                                         free(temp->name);
132                                         temp->name = NULL;
133                                 }
134                                 temp->name = strdup((char*)key);
135                                 xmlFree(key);
136                                 key = NULL;
137                         } else {
138                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_NAME);
139                         }
140                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_ID)) {
141                         key = xmlNodeGetContent(cur);
142                         if (NULL != key) {
143                                 if (NULL != temp->uuid) {
144                                         free(temp->uuid);
145                                         temp->uuid = NULL;
146                                 }
147                                 temp->uuid = strdup((char*)key);
148                                 xmlFree(key);
149                                 key = NULL;
150                         } else {
151                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_ID);
152                         }
153                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_SETTING)) {
154                         key = xmlNodeGetContent(cur);
155                         if (NULL != key) {
156                                 if (NULL != temp->setting) {
157                                         free(temp->setting);
158                                         temp->setting = NULL;
159                                 }
160                                 temp->setting = strdup((char*)key);
161                                 xmlFree(key);
162                                 key = NULL;
163                         } else {
164                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_SETTING);
165                         }
166                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE_SET)) {
167                         xmlNodePtr voice_node = NULL;
168                         voice_node = cur->xmlChildrenNode;
169
170                         while (NULL != voice_node) {
171                                 if (0 == xmlStrcmp(voice_node->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE)) {
172                                         tts_config_voice_s* temp_voice = (tts_config_voice_s*)calloc(1, sizeof(tts_config_voice_s));
173                                         if (NULL == temp_voice) {
174                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory");
175                                                 break;
176                                         }
177
178                                         attr = xmlGetProp(voice_node, (const xmlChar*)TTS_TAG_ENGINE_VOICE_TYPE);
179                                         if (NULL != attr) {
180                                                 if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
181                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
182                                                 } else if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
183                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
184                                                 } else if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
185                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
186                                                 } else {
187                                                         temp_voice->type = (int)TTS_CONFIG_VOICE_TYPE_USER_DEFINED;
188                                                 }
189                                                 xmlFree(attr);
190                                                 attr = NULL;
191                                         } else {
192                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE_TYPE);
193                                                 free(temp_voice);
194                                                 temp_voice = NULL;
195                                                 continue;
196                                         }
197
198                                         key = xmlNodeGetContent(voice_node);
199                                         if (NULL != key) {
200                                                 if (NULL != temp_voice->language) {
201                                                         free(temp_voice->language);
202                                                         temp_voice->language = NULL;
203                                                 }
204                                                 temp_voice->language = strdup((char*)key);
205                                                 xmlFree(key);
206                                                 key = NULL;
207                                                 temp->voices = g_slist_append(temp->voices, temp_voice);
208                                         } else {
209                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE);
210                                                 if (NULL != temp_voice) {
211                                                         free(temp_voice);
212                                                         temp_voice = NULL;
213                                                 }
214                                         }
215                                 }
216                                 voice_node = voice_node->next;
217                         }
218                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_PITCH_SUPPORT)) {
219                         key = xmlNodeGetContent(cur);
220                         if (NULL != key) {
221                                 if (0 == xmlStrcmp(key, (const xmlChar *)"true")) {
222                                         temp->pitch_support = true;
223                                 }
224                                 xmlFree(key);
225                                 key = NULL;
226                         } else {
227                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_PITCH_SUPPORT);
228                         }
229                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_TEXT_SIZE)) {
230                         isTextsize = true;
231                         key = xmlNodeGetContent(cur);
232                         if (NULL != key) {
233                                 temp->text_size = atoi((char*)key);
234                                 xmlFree(key);
235                         } else {
236                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[INFO] text size is unlimited.");
237                                 temp->text_size = 0;
238                         }
239                 }
240                 cur = cur->next;
241         }
242
243         if (false == isTextsize) {
244                 temp->text_size = TTS_MAX_TEXT_SIZE;
245         }
246
247         if (NULL != doc) {
248                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] doc path(%s, %p)", path, doc);
249                 xmlFreeDoc(doc);
250                 doc = NULL;
251         }
252
253         if (NULL == temp->uuid) {
254                 /* Invalid engine */
255                 SECURE_SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Invalid engine : %s", path);
256                 tts_parser_free_engine_info(temp);
257                 return -1;
258         }
259
260         *engine_info = temp;
261
262         return 0;
263 }
264
265 int tts_parser_free_engine_info(tts_engine_info_s* engine_info)
266 {
267         if (NULL == engine_info) {
268                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
269                 return -1;
270         }
271
272         if (NULL != engine_info->name) {
273                 free(engine_info->name);
274                 engine_info->name = NULL;
275         }
276         if (NULL != engine_info->uuid) {
277                 free(engine_info->uuid);
278                 engine_info->uuid = NULL;
279         }
280         if (NULL != engine_info->setting) {
281                 free(engine_info->setting);
282                 engine_info->setting = NULL;
283         }
284
285         tts_config_voice_s *temp_voice;
286         temp_voice = g_slist_nth_data(engine_info->voices, 0);
287
288         while (NULL != temp_voice) {
289                 if (NULL != temp_voice) {
290                         if (NULL != temp_voice->language) {
291                                 free(temp_voice->language);
292                                 temp_voice->language = NULL;
293                         }
294                         engine_info->voices = g_slist_remove(engine_info->voices, temp_voice);
295                         free(temp_voice);
296                         temp_voice = NULL;
297                 }
298
299                 temp_voice = g_slist_nth_data(engine_info->voices, 0);
300         }
301
302         if (NULL != engine_info) {
303                 free(engine_info);
304                 engine_info = NULL;
305         }
306
307         return 0;
308 }
309
310 int tts_parser_print_engine_info(tts_engine_info_s* engine_info)
311 {
312         if (NULL == engine_info) {
313                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
314                 return -1;
315         }
316
317         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "== get engine info ==");
318         SLOG(LOG_DEBUG, TAG_TTSCONFIG, " name : %s", engine_info->name);
319         SLOG(LOG_DEBUG, TAG_TTSCONFIG, " id   : %s", engine_info->uuid);
320         if (NULL != engine_info->setting)
321                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, " setting : %s", engine_info->setting);
322
323         SLOG(LOG_DEBUG, TAG_TTSCONFIG, " voices");
324         GSList *iter = NULL;
325         tts_config_voice_s *temp_voice;
326
327         if (g_slist_length(engine_info->voices) > 0) {
328                 /* Get a first item */
329                 iter = g_slist_nth(engine_info->voices, 0);
330
331                 int i = 1;
332                 while (NULL != iter) {
333                         /*Get handle data from list*/
334                         temp_voice = iter->data;
335
336                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "  [%dth] type(%d) lang(%s)", 
337                                 i, temp_voice->type, temp_voice->language);
338
339                         /*Get next item*/
340                         iter = g_slist_next(iter);
341                         i++;
342                 }
343         } else {
344                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "  Voice is NONE");
345         }
346
347         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "@@@");
348
349         return 0;
350 }
351
352 int tts_parser_load_config(tts_config_s** config_info)
353 {
354         if (NULL == config_info) {
355                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
356                 return -1;
357         }
358
359         xmlDocPtr doc = NULL;
360         xmlNodePtr cur = NULL;
361         xmlChar *key;
362         bool is_default_open = false;
363
364         /* For Thread safety */
365         xmlInitParser();
366
367         if (0 != access(TTS_CONFIG, F_OK)) {
368                 doc = xmlParseFile(TTS_DEFAULT_CONFIG);
369                 if (doc == NULL) {
370                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
371                         xmlCleanupParser();
372                         return -1;
373                 }
374                 is_default_open = true;
375         } else {
376                 int retry_count = 0;
377
378                 while (NULL == doc) {
379                         doc = xmlParseFile(TTS_CONFIG);
380                         if (NULL != doc) {
381                                 break;
382                         }
383                         retry_count++;
384                         usleep(10000);
385
386                         if (TTS_RETRY_COUNT == retry_count) {
387                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
388                                 doc = xmlParseFile(TTS_DEFAULT_CONFIG);
389                                 if (NULL == doc) {
390                                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_DEFAULT_CONFIG);
391                                         xmlCleanupParser();
392                                         return -1;
393                                 }
394                                 is_default_open = true;
395                                 break;
396                         }
397                 }
398         }
399
400         cur = xmlDocGetRootElement(doc);
401         if (cur == NULL) {
402                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
403                 xmlFreeDoc(doc);
404                 doc = NULL;
405                 xmlCleanupParser();
406                 return -1;
407         }
408
409         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
410                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s. doc(%p)", TTS_TAG_CONFIG_BASE_TAG, doc);
411                 xmlFreeDoc(doc);
412                 doc = NULL;
413                 xmlCleanupParser();
414                 return -1;
415         }
416
417         cur = cur->xmlChildrenNode;
418         if (cur == NULL) {
419                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
420                 xmlFreeDoc(doc);
421                 doc = NULL;
422                 xmlCleanupParser();
423                 return -1;
424         }
425
426         /* alloc engine info */
427         tts_config_s* temp;
428         temp = (tts_config_s*)calloc(1, sizeof(tts_config_s));
429         if (NULL == temp) {
430                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Out of memory(%p)", doc);
431                 xmlFreeDoc(doc);
432                 doc = NULL;
433                 xmlCleanupParser();
434                 return -1;
435         }
436
437         memset(g_engine_id, '\0', sizeof(g_engine_id));
438         memset(g_setting, '\0', sizeof(g_setting));
439         memset(g_language, '\0', sizeof(g_language));
440
441         temp->engine_id = g_engine_id;
442         temp->setting = g_setting;
443         temp->language = g_language;
444
445         while (cur != NULL) {
446                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_ID)) {
447                         key = xmlNodeGetContent(cur);
448                         if (NULL != key) {
449                                 strncpy(temp->engine_id, (char*)key, sizeof(g_engine_id) - 1);
450                                 xmlFree(key);
451                                 key = NULL;
452                         } else {
453                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] engine id is NULL");
454                         }
455                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_SETTING)) {
456                         key = xmlNodeGetContent(cur);
457                         if (NULL != key) {
458                                 strncpy(temp->setting, (char*)key, sizeof(g_setting) - 1);
459                                 xmlFree(key);
460                                 key = NULL;
461                         } else {
462                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] setting path is NULL");
463                         }
464                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_AUTO_VOICE)) {
465                         key = xmlNodeGetContent(cur);
466                         if (NULL != key) {
467                                 if (0 == xmlStrcmp(key, (const xmlChar *)"on")) {
468                                         temp->auto_voice = true;
469                                 } else if (0 == xmlStrcmp(key, (const xmlChar *)"off")) {
470                                         temp->auto_voice = false;
471                                 } else {
472                                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "Auto voice is wrong");
473                                         temp->auto_voice = true;
474                                 }
475
476                                 xmlFree(key);
477                                 key = NULL;
478                         } else {
479                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] voice type is NULL");
480                         }
481                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
482                         key = xmlNodeGetContent(cur);
483                         if (NULL != key) {
484                                 if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
485                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
486                                 } else if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
487                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
488                                 } else if (0 == xmlStrcmp(key, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
489                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
490                                 } else {
491                                         SLOG(LOG_WARN, TAG_TTSCONFIG, "Voice type is user defined");
492                                         temp->type = (int)TTS_CONFIG_VOICE_TYPE_USER_DEFINED;
493                                 }
494
495                                 xmlFree(key);
496                                 key = NULL;
497                         } else {
498                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] voice type is NULL");
499                         }
500                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
501                         key = xmlNodeGetContent(cur);
502                         if (NULL != key) {
503                                 strncpy(temp->language, (char*)key, sizeof(g_language) - 1);
504                                 xmlFree(key);
505                                 key = NULL;
506                         } else {
507                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] engine uuid is NULL");
508                         }
509
510                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_SPEECH_RATE)) {
511                         key = xmlNodeGetContent(cur);
512                         if (NULL != key) {
513                                 temp->speech_rate = atoi((char*)key);
514                                 xmlFree(key);
515                         } else {
516                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] speech rate is NULL");
517                         }
518                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_PITCH)) {
519                         key = xmlNodeGetContent(cur);
520                         if (NULL != key) {
521                                 temp->pitch = atoi((char*)key);
522                                 xmlFree(key);
523                                 key = NULL;
524                         } else {
525                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Pitch is NULL");
526                         }
527                 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
528                         key = xmlNodeGetContent(cur);
529                         if (NULL != key) {
530                                 temp->bg_volume_ratio = atof((char*)key);
531                                 xmlFree(key);
532                                 key = NULL;
533                         } else {
534                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Background volume ratio is NULL");
535                         }
536                 } else {
537
538                 }
539
540                 cur = cur->next;
541         }
542
543         *config_info = temp;
544         g_config_doc = doc;
545
546         if (true == is_default_open) {
547                 int retry_count = 0;
548                 int ret = -1;
549                 do {
550                         ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
551                         if (0 < ret)
552                                 break;
553                         retry_count++;
554                         usleep(10000);
555
556                         if (TTS_RETRY_COUNT == retry_count) {
557                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
558                                 return -1;
559                         }
560                 } while (0 != ret);
561
562                 /* Set mode */
563                 if (0 > chmod(TTS_CONFIG, 0600)) {
564                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file mode : %d", ret);
565                 }
566
567                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Default config is changed : pid(%d)", getpid());
568         }
569
570         return 0;
571 }
572
573 int tts_parser_unload_config(tts_config_s* config_info)
574 {
575         if (NULL != g_config_doc) {
576                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
577                 xmlFreeDoc(g_config_doc);
578                 g_config_doc = NULL;
579         }
580         if (NULL != config_info) {
581                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free config_info(%p)", config_info);
582                 free(config_info);
583                 config_info = NULL;
584         }
585
586         xmlCleanupParser();
587
588         return 0;
589 }
590
591
592 int tts_parser_copy_xml(const char* original, const char* destination)
593 {
594         if (NULL == original || NULL == destination) {
595                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
596                 return -1;
597         }
598
599         xmlDocPtr doc = NULL;
600         if (0 == access(original, F_OK)) {
601                 SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", original);
602                 doc = xmlParseFile(original);
603                 if (doc == NULL) {
604                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", original);
605                         return -1;
606                 }
607         } else {
608                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", original);
609                 return -1;
610         }
611
612         int ret = xmlSaveFile(destination, doc);
613         if (0 > ret) {
614                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
615         } else {
616                 static FILE* pFile;
617                 pFile = fopen(destination, "r");
618                 int fd = -1;
619                 if (NULL == pFile) {
620                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", destination);
621                 } else {
622                         fd = fileno(pFile);
623                         fsync(fd);
624                         fclose(pFile);
625                         SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", destination);
626                 }
627                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", destination);
628         }
629
630         /* Set mode */
631         if (0 > chmod(destination, 0600)) {
632                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to change file mode : %d", ret);
633         }
634
635         if (NULL != doc) {
636                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] doc(%p)", doc);
637                 xmlFreeDoc(doc);
638                 doc = NULL;
639         }
640
641         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[SUCCESS] Copying xml");
642
643         return 0;
644 }
645
646 int tts_parser_set_engine(const char* engine_id, const char* setting, const char* language, int type)
647 {
648         if (NULL == engine_id) {
649                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
650                 return -1;
651         }
652
653         xmlNodePtr cur = NULL;
654         cur = xmlDocGetRootElement(g_config_doc);
655         if (cur == NULL) {
656                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
657                 return -1;
658         }
659
660         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
661                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
662                 return -1;
663         }
664
665         cur = cur->xmlChildrenNode;
666         if (cur == NULL) {
667                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
668                 return -1;
669         }
670
671         while (cur != NULL) {
672                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_ID)) {
673                         xmlNodeSetContent(cur, (const xmlChar *)engine_id);
674                 }
675
676                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
677                         xmlNodeSetContent(cur, (const xmlChar *)language);
678                 }
679
680                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_SETTING)) {
681                         xmlNodeSetContent(cur, (const xmlChar *)setting);
682                 }
683
684                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
685                         switch (type) {
686                         case TTS_CONFIG_VOICE_TYPE_MALE:        xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);        break;
687                         case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
688                         case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
689                         default:                                xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
690                         }
691                 }
692
693                 cur = cur->next;
694         }
695
696         if (0 == access(TTS_CONFIG, F_OK)) {
697                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
698                 if (0 > ret) {
699                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
700                 } else {
701                         static FILE* pFile;
702                         pFile = fopen(TTS_CONFIG, "r");
703                         int fd = -1;
704                         if (NULL == pFile) {
705                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
706                         } else {
707                                 fd = fileno(pFile);
708                                 fsync(fd);
709                                 fclose(pFile);
710                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
711                         }
712                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
713                 }
714         } else {
715                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
716         }
717
718         return 0;
719 }
720
721 int tts_parser_set_voice(const char* language, int type)
722 {
723         if (NULL == language) {
724                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
725                 return -1;
726         }
727
728         xmlNodePtr cur = NULL;
729         cur = xmlDocGetRootElement(g_config_doc);
730         if (cur == NULL) {
731                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
732                 return -1;
733         }
734
735         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
736                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
737                 return -1;
738         }
739
740         cur = cur->xmlChildrenNode;
741         if (cur == NULL) {
742                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
743                 return -1;
744         }
745
746         while (cur != NULL) {
747                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
748                         xmlNodeSetContent(cur, (const xmlChar *)language);
749                 }
750
751                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
752                         switch (type) {
753                         case TTS_CONFIG_VOICE_TYPE_MALE:        xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);        break;
754                         case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
755                         case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
756                         default:
757                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Invalid type : %d", type);
758                                 xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);
759                                 break;
760                         }
761                 }
762
763                 cur = cur->next;
764         }
765
766         if (0 == access(TTS_CONFIG, F_OK)) {
767                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
768                 if (0 > ret) {
769                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
770                 } else {
771                         static FILE* pFile;
772                         pFile = fopen(TTS_CONFIG, "r");
773                         int fd = -1;
774                         if (NULL == pFile) {
775                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
776                         } else {
777                                 fd = fileno(pFile);
778                                 fsync(fd);
779                                 fclose(pFile);
780                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
781                         }
782                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
783                 }
784         } else {
785                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
786         }
787         return 0;
788 }
789
790 int tts_parser_set_auto_voice(bool value)
791 {
792         xmlNodePtr cur = NULL;
793         cur = xmlDocGetRootElement(g_config_doc);
794         if (cur == NULL) {
795                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
796                 return -1;
797         }
798
799         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
800                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
801                 return -1;
802         }
803
804         cur = cur->xmlChildrenNode;
805         if (cur == NULL) {
806                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
807                 return -1;
808         }
809
810         while (cur != NULL) {
811                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_AUTO_VOICE)) {
812                         if (true == value) {
813                                 xmlNodeSetContent(cur, (const xmlChar *)"on");
814                         } else if (false == value) {
815                                 xmlNodeSetContent(cur, (const xmlChar *)"off");
816                         } else {
817                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong value of auto voice");
818                                 return -1;
819                         }
820                         break;
821                 }
822                 cur = cur->next;
823         }
824
825         if (0 == access(TTS_CONFIG, F_OK)) {
826                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
827                 if (0 > ret) {
828                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
829                 } else {
830                         static FILE* pFile;
831                         pFile = fopen(TTS_CONFIG, "r");
832                         int fd = -1;
833                         if (NULL == pFile) {
834                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
835                         } else {
836                                 fd = fileno(pFile);
837                                 fsync(fd);
838                                 fclose(pFile);
839                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
840                         }
841                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
842                 }
843         } else {
844                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
845         }
846
847         return 0;
848 }
849
850 int tts_parser_set_speech_rate(int value)
851 {
852         xmlNodePtr cur = NULL;
853         cur = xmlDocGetRootElement(g_config_doc);
854         if (cur == NULL) {
855                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
856                 return -1;
857         }
858
859         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
860                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
861                 return -1;
862         }
863
864         cur = cur->xmlChildrenNode;
865         if (cur == NULL) {
866                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
867                 return -1;
868         }
869
870         while (cur != NULL) {
871                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_SPEECH_RATE)) {
872                         char temp[10];
873                         memset(temp, '\0', 10);
874                         snprintf(temp, 10, "%d", value);
875
876                         xmlNodeSetContent(cur, (const xmlChar *)temp);
877
878                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Set speech rate : %s", temp);
879                         break;
880                 }
881
882                 cur = cur->next;
883         }
884
885         if (0 == access(TTS_CONFIG, F_OK)) {
886                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
887                 if (0 > ret) {
888                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
889                 } else {
890                         static FILE* pFile;
891                         pFile = fopen(TTS_CONFIG, "r");
892                         int fd = -1;
893                         if (NULL == pFile) {
894                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
895                         } else {
896                                 fd = fileno(pFile);
897                                 fsync(fd);
898                                 fclose(pFile);
899                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
900                         }
901                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
902                 }
903         } else {
904                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
905         }
906
907         return 0;
908 }
909
910 int tts_parser_set_pitch(int value)
911 {
912         xmlNodePtr cur = NULL;
913         cur = xmlDocGetRootElement(g_config_doc);
914         if (cur == NULL) {
915                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
916                 return -1;
917         }
918
919         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
920                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
921                 return -1;
922         }
923
924         cur = cur->xmlChildrenNode;
925         if (cur == NULL) {
926                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
927                 return -1;
928         }
929
930         while (cur != NULL) {
931                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_PITCH)) {
932                         char temp[10];
933                         memset(temp, '\0', 10);
934                         snprintf(temp, 10, "%d", value);
935                         xmlNodeSetContent(cur, (const xmlChar *)temp);
936                         break;
937                 }
938
939                 cur = cur->next;
940         }
941
942         if (0 == access(TTS_CONFIG, F_OK)) {
943                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
944                 if (0 > ret) {
945                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
946                 } else {
947                         static FILE* pFile;
948                         pFile = fopen(TTS_CONFIG, "r");
949                         int fd = -1;
950                         if (NULL == pFile) {
951                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
952                         } else {
953                                 fd = fileno(pFile);
954                                 fsync(fd);
955                                 fclose(pFile);
956                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
957                         }
958                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
959                 }
960         } else {
961                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
962         }
963
964         return 0;
965 }
966
967 int tts_parser_set_bg_volume_ratio(double value)
968 {
969         xmlNodePtr cur = NULL;
970         cur = xmlDocGetRootElement(g_config_doc);
971         if (cur == NULL) {
972                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
973                 return -1;
974         }
975
976         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
977                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
978                 return -1;
979         }
980
981         cur = cur->xmlChildrenNode;
982         if (cur == NULL) {
983                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document");
984                 return -1;
985         }
986
987         while (cur != NULL) {
988                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
989                         char temp[10];
990                         memset(temp, '\0', 10);
991                         snprintf(temp, 10, "%lf", value);
992                         xmlNodeSetContent(cur, (const xmlChar *)temp);
993                         break;
994                 }
995
996                 cur = cur->next;
997         }
998
999         if (0 == access(TTS_CONFIG, F_OK)) {
1000                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
1001                 if (0 > ret) {
1002                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Save result : %d", ret);
1003                 } else {
1004                         static FILE* pFile;
1005                         pFile = fopen(TTS_CONFIG, "r");
1006                         int fd = -1;
1007                         if (NULL == pFile) {
1008                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
1009                         } else {
1010                                 fd = fileno(pFile);
1011                                 fsync(fd);
1012                                 fclose(pFile);
1013                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
1014                         }
1015                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
1016                 }
1017         } else {
1018                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
1019         }
1020
1021         return 0;
1022 }
1023
1024 int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voice, char** language, int* voice_type, 
1025                                    int* speech_rate, int* pitch, double* bg_volume_ratio)
1026 {
1027         if (NULL == engine || NULL == setting || NULL == language || NULL == voice_type || NULL == speech_rate) {
1028                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input parameter is NULL");
1029                 return -1;
1030         }
1031
1032         xmlDocPtr doc = NULL;
1033         xmlNodePtr cur_new = NULL;
1034         xmlNodePtr cur_old = NULL;
1035
1036         xmlChar *key_new;
1037         xmlChar *key_old;
1038
1039         int retry_count = 0;
1040         while (NULL == doc) {
1041                 if (0 == access(TTS_CONFIG, F_OK)) {
1042                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Success to access to %s", TTS_CONFIG);
1043                         doc = xmlParseFile(TTS_CONFIG);
1044                         if (NULL != doc) {
1045                                 break;
1046                         }
1047                 }
1048                 retry_count++;
1049                 usleep(10000);
1050
1051                 if (TTS_RETRY_COUNT == retry_count) {
1052                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
1053                         return -1;
1054                 }
1055         }
1056
1057         cur_new = xmlDocGetRootElement(doc);
1058         cur_old = xmlDocGetRootElement(g_config_doc);
1059         if (cur_new == NULL || cur_old == NULL) {
1060                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
1061                 xmlFreeDoc(doc);
1062                 doc = NULL;
1063                 return -1;
1064         }
1065
1066         if (xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG) || 
1067         xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG)) {
1068                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] The wrong type, root node is NOT %s. doc(%p)", TTS_TAG_CONFIG_BASE_TAG, doc);
1069                 xmlFreeDoc(doc);
1070                 doc = NULL;
1071                 return -1;
1072         }
1073
1074         cur_new = cur_new->xmlChildrenNode;
1075         cur_old = cur_old->xmlChildrenNode;
1076         if (cur_new == NULL || cur_old == NULL) {
1077                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Empty document(%p)", doc);
1078                 xmlFreeDoc(doc);
1079                 doc = NULL;
1080                 return -1;
1081         }
1082
1083         while (cur_new != NULL && cur_old != NULL) {
1084                 if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_ID)) {
1085                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_ID)) {
1086                                 key_old = xmlNodeGetContent(cur_old);
1087                                 if (NULL != key_old) {
1088                                         key_new = xmlNodeGetContent(cur_new);
1089                                         if (NULL != key_new) {
1090                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1091                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old engine id(%s), New engine(%s)", 
1092                                                                 (char*)key_old, (char*)key_new);
1093                                                         if (NULL != *engine) {
1094                                                                 free(*engine);
1095                                                                 *engine = NULL;
1096                                                         }
1097                                                         *engine = strdup((char*)key_new);
1098                                                 }
1099                                                 xmlFree(key_new);
1100                                                 key_new = NULL;
1101                                         }
1102                                         xmlFree(key_old);
1103                                         key_old = NULL;
1104                                 }
1105                         } else {
1106                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1107                         }
1108                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
1109                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
1110                                 key_old = xmlNodeGetContent(cur_old);
1111                                 if (NULL != key_old) {
1112                                         key_new = xmlNodeGetContent(cur_new);
1113                                         if (NULL != key_new) {
1114                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1115                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old engine setting(%s), New engine setting(%s)", 
1116                                                                 (char*)key_old, (char*)key_new);
1117                                                         if (NULL != *setting) {
1118                                                                 free(*setting);
1119                                                                 *setting = NULL;
1120                                                         }
1121                                                         *setting = strdup((char*)key_new);
1122                                                 }
1123                                                 xmlFree(key_new);
1124                                                 key_new = NULL;
1125                                         }
1126                                         xmlFree(key_old);
1127                                         key_old = NULL;
1128                                 }
1129                         } else {
1130                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1131                         }
1132                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
1133                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
1134                                 key_old = xmlNodeGetContent(cur_old);
1135                                 if (NULL != key_old) {
1136                                         key_new = xmlNodeGetContent(cur_new);
1137                                         if (NULL != key_new) {
1138                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1139                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old auto voice (%s), New auto voice(%s)", 
1140                                                                 (char*)key_old, (char*)key_new);
1141                                                         if (0 == xmlStrcmp((const xmlChar*)"on", key_new)) {
1142                                                                 *auto_voice = true;
1143                                                         } else {
1144                                                                 *auto_voice = false;
1145                                                         }
1146                                                 }
1147                                                 xmlFree(key_new);
1148                                                 key_new = NULL;
1149                                         }
1150                                         xmlFree(key_old);
1151                                         key_old = NULL;
1152                                 }
1153                         } else {
1154                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1155                         }
1156                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
1157                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
1158                                 key_old = xmlNodeGetContent(cur_old);
1159                                 if (NULL != key_old) {
1160                                         key_new = xmlNodeGetContent(cur_new);
1161                                         if (NULL != key_new) {
1162                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1163                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old language(%s), New language(%s)", 
1164                                                                 (char*)key_old, (char*)key_new);
1165                                                         if (NULL != *language) {
1166                                                                 free(*language);
1167                                                                 *language = NULL;
1168                                                         }
1169                                                         *language = strdup((char*)key_new);
1170                                                 }
1171                                                 xmlFree(key_new);
1172                                                 key_new = NULL;
1173                                         }
1174                                         xmlFree(key_old);
1175                                         key_old = NULL;
1176                                 }
1177                         } else {
1178                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1179                         }
1180                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
1181                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
1182                                 key_old = xmlNodeGetContent(cur_old);
1183                                 if (NULL != key_old) {
1184                                         key_new = xmlNodeGetContent(cur_new);
1185                                         if (NULL != key_new) {
1186                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1187                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old voice type(%s), New voice type(%s)", 
1188                                                                 (char*)key_old, (char*)key_new);
1189                                                         if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
1190                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
1191                                                         } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
1192                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
1193                                                         } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
1194                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
1195                                                         } else {
1196                                                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] New voice type is not valid");
1197                                                         }
1198                                                 }
1199                                                 xmlFree(key_new);
1200                                                 key_new = NULL;
1201                                         }
1202                                         xmlFree(key_old);
1203                                         key_old = NULL;
1204                                 }
1205                         } else {
1206                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1207                         }
1208                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
1209                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
1210                                 key_old = xmlNodeGetContent(cur_old);
1211                                 if (NULL != key_old) {
1212                                         key_new = xmlNodeGetContent(cur_new);
1213                                         if (NULL != key_new) {
1214                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1215                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old speech rate(%s), New speech rate(%s)", 
1216                                                                 (char*)key_old, (char*)key_new);
1217                                                         *speech_rate = atoi((char*)key_new);
1218                                                 }
1219                                                 xmlFree(key_new);
1220                                                 key_new = NULL;
1221                                         }
1222                                         xmlFree(key_old);
1223                                         key_old = NULL;
1224                                 }
1225                         } else {
1226                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1227                         }
1228                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
1229                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
1230                                 key_old = xmlNodeGetContent(cur_old);
1231                                 if (NULL != key_old) {
1232                                         key_new = xmlNodeGetContent(cur_new);
1233                                         if (NULL != key_new) {
1234                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1235                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old pitch(%s), New pitch(%s)", 
1236                                                                 (char*)key_old, (char*)key_new);
1237                                                         *pitch = atoi((char*)key_new);
1238                                                 }
1239                                                 xmlFree(key_new);
1240                                                 key_new = NULL;
1241                                         }
1242                                         xmlFree(key_old);
1243                                         key_old = NULL;
1244                                 }
1245                         } else {
1246                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1247                         }
1248                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
1249                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BACKGROUND_VOLUME_RATIO)) {
1250                                 key_old = xmlNodeGetContent(cur_old);
1251                                 if (NULL != key_old) {
1252                                         key_new = xmlNodeGetContent(cur_new);
1253                                         if (NULL != key_new) {
1254                                                 if (0 != xmlStrcmp(key_old, key_new)) {
1255                                                         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "Old bg volume ratio(%s), New bg volume ratio(%s)", 
1256                                                                 (char*)key_old, (char*)key_new);
1257                                                         *bg_volume_ratio = atof((char*)key_new);
1258                                                 }
1259                                                 xmlFree(key_new);
1260                                                 key_new = NULL;
1261                                         }
1262                                         xmlFree(key_old);
1263                                         key_old = NULL;
1264                                 }
1265                         } else {
1266                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] old config and new config are different");
1267                         }
1268                 } else {
1269
1270                 }
1271
1272                 cur_new = cur_new->next;
1273                 cur_old = cur_old->next;
1274         }
1275
1276         if (NULL != g_config_doc) {
1277                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
1278                 xmlFreeDoc(g_config_doc);
1279                 g_config_doc = NULL;
1280         }
1281         g_config_doc = doc;
1282
1283         return 0;
1284 }
1285
1286 int tts_parser_reset()
1287 {
1288         SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] Reset g_config_doc as %s", TTS_DEFAULT_CONFIG);
1289
1290         if (NULL != g_config_doc) {
1291                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Free g_config_doc(%p)", g_config_doc);
1292                 xmlFreeDoc(g_config_doc);
1293                 g_config_doc = NULL;
1294         }
1295
1296         g_config_doc = xmlParseFile(TTS_DEFAULT_CONFIG);
1297         if (NULL == g_config_doc) {
1298                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to parse %s", TTS_DEFAULT_CONFIG);
1299                 return -1;
1300         }
1301
1302         if (0 == access(TTS_CONFIG, F_OK)) {
1303                 int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
1304                 if (0 > ret) {
1305                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to save %s", TTS_CONFIG);
1306                 } else {
1307                         static FILE* pFile;
1308                         pFile = fopen(TTS_CONFIG, "r");
1309                         int fd = -1;
1310                         if (NULL == pFile) {
1311                                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to open file %s", TTS_CONFIG);
1312                         } else {
1313                                 fd = fileno(pFile);
1314                                 fsync(fd);
1315                                 fclose(pFile);
1316                                 SLOG(LOG_INFO, TAG_TTSCONFIG, "[DEBUG] Success to fsync %s", TTS_CONFIG);
1317                         }
1318                         SLOG(LOG_ERROR, TAG_TTSCONFIG, "[DEBUG] Success to save %s", TTS_CONFIG);
1319                 }
1320         } else {
1321                 SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to access to %s", TTS_CONFIG);
1322         }
1323
1324         return 0;
1325 }