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