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