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