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