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