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