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