Fix svace issues
[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)     free(config_info->engine_id);
477                 if (NULL != config_info->setting)       free(config_info->setting);
478                 if (NULL != config_info->language)      free(config_info->language);
479                 free(config_info);
480         }
481
482         return 0;
483 }
484
485
486 int tts_parser_copy_xml(const char* original, const char* destination)
487 {
488         if (NULL == original || NULL == destination) {
489                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
490                 return -1;
491         }
492
493         xmlDocPtr doc = NULL;
494         doc = xmlParseFile(original);
495         if (doc == NULL) {
496                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to parse file error : %s", original);
497                 return -1;
498         }
499
500         int ret = xmlSaveFile(destination, doc);
501         if (0 > ret) {
502                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
503         }
504
505         /* Set mode */
506         if (0 > chmod(destination, 0666)) {
507                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to change file mode : %d", ret);
508         }
509
510         xmlFreeDoc(doc);
511         SLOG(LOG_DEBUG, tts_tag(), "[SUCCESS] Copying xml");
512
513         return 0;
514 }
515
516 int tts_parser_set_engine(const char* engine_id, const char* setting, const char* language, int type)
517 {
518         if (NULL == engine_id) {
519                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
520                 return -1;
521         }
522
523         xmlNodePtr cur = NULL;
524         cur = xmlDocGetRootElement(g_config_doc);
525         if (cur == NULL) {
526                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
527                 return -1;
528         }
529
530         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
531                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
532                 return -1;
533         }
534
535         cur = cur->xmlChildrenNode;
536         if (cur == NULL) {
537                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
538                 return -1;
539         }
540
541         while (cur != NULL) {
542                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_ID)) {
543                         xmlNodeSetContent(cur, (const xmlChar *)engine_id);
544                 }
545
546                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
547                         xmlNodeSetContent(cur, (const xmlChar *)language);
548                 }
549
550                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_ENGINE_SETTING)) {
551                         xmlNodeSetContent(cur, (const xmlChar *)setting);
552                 }
553
554                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
555                         switch (type) {
556                         case TTS_CONFIG_VOICE_TYPE_MALE:        xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);        break;
557                         case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
558                         case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
559                         default:                                xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
560                         }
561                 }
562                 
563                 cur = cur->next;
564         }
565
566         int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
567         if (0 > ret) {
568                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
569         }
570
571         return 0;
572 }
573
574 int tts_parser_set_voice(const char* language, int type)
575 {
576         if (NULL == language) {
577                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
578                 return -1;
579         }
580
581         xmlNodePtr cur = NULL;
582         cur = xmlDocGetRootElement(g_config_doc);
583         if (cur == NULL) {
584                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
585                 return -1;
586         }
587
588         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
589                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
590                 return -1;
591         }
592
593         cur = cur->xmlChildrenNode;
594         if (cur == NULL) {
595                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
596                 return -1;
597         }
598
599         while (cur != NULL) {
600                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_LANGUAGE)) {
601                         xmlNodeSetContent(cur, (const xmlChar *)language);
602                 } 
603
604                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_VOICE_TYPE)) {
605                         switch (type) {
606                         case TTS_CONFIG_VOICE_TYPE_MALE:        xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);        break;
607                         case TTS_CONFIG_VOICE_TYPE_FEMALE:      xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);      break;
608                         case TTS_CONFIG_VOICE_TYPE_CHILD:       xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_CHILD);       break;
609                         default:
610                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid type : %d", type);
611                                 xmlNodeSetContent(cur, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);
612                                 break;
613                         }
614                 }
615
616                 cur = cur->next;
617         }
618
619         int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
620         if (0 > ret) {
621                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
622         }
623
624         return 0;
625 }
626
627 int tts_parser_set_auto_voice(bool value)
628 {
629         xmlNodePtr cur = NULL;
630         cur = xmlDocGetRootElement(g_config_doc);
631         if (cur == NULL) {
632                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
633                 return -1;
634         }
635
636         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
637                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
638                 return -1;
639         }
640
641         cur = cur->xmlChildrenNode;
642         if (cur == NULL) {
643                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
644                 return -1;
645         }
646
647         while (cur != NULL) {
648                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_AUTO_VOICE)) {
649                         if (true == value) {
650                                 xmlNodeSetContent(cur, (const xmlChar *)"on");
651                         } else if (false == value) {
652                                 xmlNodeSetContent(cur, (const xmlChar *)"off");
653                         } else {
654                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong value of auto voice");
655                                 return -1;
656                         }
657                         break;
658                 }
659                 cur = cur->next;
660         }
661
662         int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
663         if (0 > ret) {
664                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
665         }
666
667         return 0;
668 }
669
670 int tts_parser_set_speech_rate(int value)
671 {
672         xmlNodePtr cur = NULL;
673         cur = xmlDocGetRootElement(g_config_doc);
674         if (cur == NULL) {
675                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
676                 return -1;
677         }
678
679         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
680                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
681                 return -1;
682         }
683
684         cur = cur->xmlChildrenNode;
685         if (cur == NULL) {
686                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
687                 return -1;
688         }
689
690         while (cur != NULL) {
691                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_SPEECH_RATE)) {
692                         char temp[10];
693                         memset(temp, '\0', 10);
694                         snprintf(temp, 10, "%d", value);
695
696                         xmlNodeSetContent(cur, (const xmlChar *)temp);
697
698                         SLOG(LOG_DEBUG, tts_tag(), "Set speech rate : %s", temp);
699                         break;
700                 }
701
702                 cur = cur->next;
703         }
704
705         int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
706         if (0 > ret) {
707                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
708         }
709
710         return 0;
711 }
712
713 int tts_parser_set_pitch(int value)
714 {
715         xmlNodePtr cur = NULL;
716         cur = xmlDocGetRootElement(g_config_doc);
717         if (cur == NULL) {
718                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
719                 return -1;
720         }
721
722         if (xmlStrcmp(cur->name, (const xmlChar *) TTS_TAG_CONFIG_BASE_TAG)) {
723                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
724                 return -1;
725         }
726
727         cur = cur->xmlChildrenNode;
728         if (cur == NULL) {
729                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
730                 return -1;
731         }
732
733         while (cur != NULL) {
734                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_CONFIG_PITCH)) {
735                         char temp[10];
736                         memset(temp, '\0', 10);
737                         snprintf(temp, 10, "%d", value);
738                         xmlNodeSetContent(cur, (const xmlChar *)temp);
739                         break;
740                 } 
741
742                 cur = cur->next;
743         }
744
745         int ret = xmlSaveFile(TTS_CONFIG, g_config_doc);
746         if (0 > ret) {
747                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Save result : %d", ret);
748         }
749
750         return 0;
751 }
752
753 int tts_parser_find_config_changed(char** engine, char**setting, bool* auto_voice, char** language, int* voice_type, 
754                                    int* speech_rate, int* pitch)
755 {
756         if (NULL == engine || NULL == setting || NULL == language || NULL == voice_type || NULL == speech_rate) {
757                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Input parameter is NULL");
758                 return -1;
759         }
760
761         xmlDocPtr doc = NULL;
762         xmlNodePtr cur_new = NULL;
763         xmlNodePtr cur_old = NULL;
764
765         xmlChar *key_new;
766         xmlChar *key_old;
767
768         int retry_count = 0;
769         while (NULL == doc) {
770                 doc = xmlParseFile(TTS_CONFIG);
771                 if (NULL != doc) {
772                         break;
773                 }
774                 retry_count++;
775                 usleep(10000);
776
777                 if (TTS_RETRY_COUNT == retry_count) {
778                         SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to parse file error : %s", TTS_CONFIG);
779                         return -1;
780                 }
781         }
782
783         cur_new = xmlDocGetRootElement(doc);
784         cur_old = xmlDocGetRootElement(g_config_doc);
785         if (cur_new == NULL || cur_old == NULL) {
786                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
787                 xmlFreeDoc(doc);
788                 doc = NULL;
789                 return -1;
790         }
791
792         if (xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG) || 
793         xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_BASE_TAG)) {
794                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] The wrong type, root node is NOT %s", TTS_TAG_CONFIG_BASE_TAG);
795                 xmlFreeDoc(doc);
796                 doc = NULL;
797                 return -1;
798         }
799
800         cur_new = cur_new->xmlChildrenNode;
801         cur_old = cur_old->xmlChildrenNode;
802         if (cur_new == NULL || cur_old == NULL) {
803                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Empty document");
804                 xmlFreeDoc(doc);
805                 doc = NULL;
806                 return -1;
807         }
808
809         while (cur_new != NULL && cur_old != NULL) {
810                 if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_ID)) {
811                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_ID)) {
812                                 key_old = xmlNodeGetContent(cur_old);
813                                 if (NULL != key_old) {
814                                         key_new = xmlNodeGetContent(cur_new);
815                                         if (NULL != key_new) {
816                                                 if (0 != xmlStrcmp(key_old, key_new)) {
817                                                         SLOG(LOG_DEBUG, tts_tag(), "Old engine id(%s), New engine(%s)", 
818                                                                 (char*)key_old, (char*)key_new);
819                                                         if (NULL != *engine)    free(*engine);
820                                                         *engine = strdup((char*)key_new);
821                                                 }
822                                                 xmlFree(key_new);
823                                         }
824                                         xmlFree(key_old);
825                                 }
826                         } else {
827                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
828                         }
829                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
830                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_ENGINE_SETTING)) {
831                                 key_old = xmlNodeGetContent(cur_old);
832                                 if (NULL != key_old) {
833                                         key_new = xmlNodeGetContent(cur_new);
834                                         if (NULL != key_new) {
835                                                 if (0 != xmlStrcmp(key_old, key_new)) {
836                                                         SLOG(LOG_DEBUG, tts_tag(), "Old engine setting(%s), New engine setting(%s)", 
837                                                                 (char*)key_old, (char*)key_new);
838                                                         if (NULL != *setting)   free(*setting);
839                                                         *setting = strdup((char*)key_new);
840                                                 }
841                                                 xmlFree(key_new);
842                                         }
843                                         xmlFree(key_old);
844                                 }
845                         } else {
846                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
847                         }
848                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
849                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_AUTO_VOICE)) {
850                                 key_old = xmlNodeGetContent(cur_old);
851                                 if (NULL != key_old) {
852                                         key_new = xmlNodeGetContent(cur_new);
853                                         if (NULL != key_new) {
854                                                 if (0 != xmlStrcmp(key_old, key_new)) {
855                                                         SLOG(LOG_DEBUG, tts_tag(), "Old auto voice (%s), New auto voice(%s)", 
856                                                                 (char*)key_old, (char*)key_new);
857                                                         if (0 == xmlStrcmp((const xmlChar*)"on", key_new)) {
858                                                                 *auto_voice = true;
859                                                         } else {
860                                                                 *auto_voice = false;
861                                                         }
862                                                 }
863                                                 xmlFree(key_new);
864                                         }
865                                         xmlFree(key_old);
866                                 }
867                         } else {
868                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
869                         }
870                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
871                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_LANGUAGE)) {
872                                 key_old = xmlNodeGetContent(cur_old);
873                                 if (NULL != key_old) {
874                                         key_new = xmlNodeGetContent(cur_new);
875                                         if (NULL != key_new) {
876                                                 if (0 != xmlStrcmp(key_old, key_new)) {
877                                                         SLOG(LOG_DEBUG, tts_tag(), "Old language(%s), New language(%s)", 
878                                                                 (char*)key_old, (char*)key_new);
879                                                         if (NULL != *language)  free(*language);
880                                                         *language = strdup((char*)key_new);
881                                                 }
882                                                 xmlFree(key_new);
883                                         }
884                                         xmlFree(key_old);
885                                 }
886                         } else {
887                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
888                         }
889                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
890                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_VOICE_TYPE)) {
891                                 key_old = xmlNodeGetContent(cur_old);
892                                 if (NULL != key_old) {
893                                         key_new = xmlNodeGetContent(cur_new);
894                                         if (NULL != key_new) {
895                                                 if (0 != xmlStrcmp(key_old, key_new)) {
896                                                         SLOG(LOG_DEBUG, tts_tag(), "Old voice type(%s), New voice type(%s)", 
897                                                                 (char*)key_old, (char*)key_new);
898                                                         if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
899                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_FEMALE;
900                                                         } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
901                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_MALE;
902                                                         } else if (0 == xmlStrcmp(key_new, (const xmlChar *)TTS_TAG_VOICE_TYPE_CHILD)) {
903                                                                 *voice_type = (int)TTS_CONFIG_VOICE_TYPE_CHILD;
904                                                         } else {
905                                                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] New voice type is not valid");
906                                                         }
907                                                 }
908                                                 xmlFree(key_new);
909                                         }
910                                         xmlFree(key_old);
911                                 }
912                         } else {
913                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
914                         }
915                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
916                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_SPEECH_RATE)) {
917                                 key_old = xmlNodeGetContent(cur_old);
918                                 if (NULL != key_old) {
919                                         key_new = xmlNodeGetContent(cur_new);
920                                         if (NULL != key_new) {
921                                                 if (0 != xmlStrcmp(key_old, key_new)) {
922                                                         SLOG(LOG_DEBUG, tts_tag(), "Old speech rate(%s), New speech rate(%s)", 
923                                                                 (char*)key_old, (char*)key_new);
924                                                         *speech_rate = atoi((char*)key_new);
925                                                 }
926                                                 xmlFree(key_new);
927                                         }
928                                         xmlFree(key_old);
929                                 }
930                         } else {
931                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
932                         }
933                 } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
934                         if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)TTS_TAG_CONFIG_PITCH)) {
935                                 key_old = xmlNodeGetContent(cur_old);
936                                 if (NULL != key_old) {
937                                         key_new = xmlNodeGetContent(cur_new);
938                                         if (NULL != key_new) {
939                                                 if (0 != xmlStrcmp(key_old, key_new)) {
940                                                         SLOG(LOG_DEBUG, tts_tag(), "Old pitch(%s), New pitch(%s)", 
941                                                                 (char*)key_old, (char*)key_new);
942                                                         *pitch = atoi((char*)key_new);
943                                                 }
944                                                 xmlFree(key_new);
945                                         }
946                                         xmlFree(key_old);
947                                 }
948                         } else {
949                                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] old config and new config are different");
950                         }
951                 } else {
952
953                 }
954
955                 cur_new = cur_new->next;
956                 cur_old = cur_old->next;
957         }
958
959         if (NULL != g_config_doc) {
960                 xmlFreeDoc(g_config_doc);
961                 g_config_doc = NULL;
962         }
963         g_config_doc = doc;
964
965         return 0;
966 }