Change internal function to static
[platform/core/uifw/tts.git] / engine-parser / src / tts-engine-parser.c
index deafadc..0f6c34d 100644 (file)
 #define TTS_TAG_ENGINE_VOICE_TYPE              "type"
 #define TTS_TAG_ENGINE_PITCH_SUPPORT           "pitch-support"
 #define TTS_TAG_ENGINE_CREDENTIAL              "credential"
+#define TTS_TAG_ENGINE_TEXT_SIZE               "text-size"
 
-#define TTS_CONFIG_BASE                tzplatform_mkpath(TZ_USER_HOME, "share/.voice")
-#define TTS_HOME               tzplatform_mkpath(TZ_USER_HOME, "share/.voice/tts")
-#define TTS_ENGINE_BASE                tzplatform_mkpath(TZ_USER_HOME, "share/.voice/tts/1.0")
-#define TTS_ENGINE_INFO                tzplatform_mkpath(TZ_USER_SHARE, ".voice/tts/1.0/engine-info")
+#define TTS_TAG_VOICE_BASE                     "tts-voice"
+
+#define TTS_CONFIG_BASE                tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.voice")
+#define TTS_HOME               tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.voice/tts")
+#define TTS_ENGINE_BASE                tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.voice/tts/1.0")
+#define TTS_ENGINE_INFO                tzplatform_mkpath(tzplatform_getid("TZ_USER_SHARE"), ".voice/tts/1.0/engine-info")
+
+#define TTS_VOICE_INFO tzplatform_mkpath(tzplatform_getid("TZ_SYS_RO_SHARE"), "voice/tts/1.0/tts-voice.xml")
 
 #define TTS_GLOBAL_CONFIG_BASE         "/etc/skel/share/.voice"
 #define TTS_GLOBAL_HOME                "/etc/skel/share/.voice/tts"
 #define TTS_METADATA_LANGUAGE                  "http://tizen.org/metadata/tts-engine/language"
 #define TTS_METADATA_CREDENTIAL_REQUIRED       "http://tizen.org/metadata/tts-engine/credential-required"
 #define TTS_METADATA_SETTING           "http://tizen.org/metadata/tts-engine/setting"
+#define TTS_METADATA_TEXT_SIZE         "http://tizen.org/metadata/tts-engine/text-size"
+#define TTS_METADATA_PITCH_SUPPORT     "http://tizen.org/metadata/tts-engine/pitch-support"
+
+#define TTS_MAX_TEXT_SIZE      "2000"
 
 /* Define Macro */
 #define FREE(x)        { if (NULL != x)        { free(x);      x = NULL; } }
@@ -77,6 +86,16 @@ typedef struct metadata {
        const char *value;
 } metadata;
 
+typedef struct {
+       char *lang;
+       char *type;
+} voice_info_s;
+
+typedef struct {
+       voice_info_s *voice_info;
+       int size;
+} voice_info_list_s;
+
 static xmlDocPtr g_doc;
 GumUser *g_guser = NULL;
 uid_t g_uid = 301;     // app_fw
@@ -89,21 +108,23 @@ char *g_dir_home = NULL;
 char *g_dir_engine_base = NULL;
 char *g_dir_engine_info = NULL;
 
+GSList *g_voice_info_list = NULL;
+
 static int __create_engine_info_xml(const char *pkgid)
 {
-       LOGD("=== Create engine info doc");
+       LOGD("@@@ Create engine info doc");
        g_doc = xmlNewDoc((xmlChar*)"1.0");
        if (NULL == g_doc) {
                LOGE("[ERROR] Fail to new doc");
                return -1;
        }
-       LOGD("===");
+       LOGD("@@@");
        return 0;
 }
 
 static int __save_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid, gid_t gid)
 {
-       LOGD("=== Save engine info doc");
+       LOGD("@@@ Save engine info doc");
        char *dir_config_base = NULL;
        char *dir_home = NULL;
        char *dir_engine_base = NULL;
@@ -267,13 +288,13 @@ static int __save_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid, gid_t
        FREE(dir_engine_base)
        FREE(dir_engine_info)
 
-       LOGD("===");
+       LOGD("@@@");
        return 0;
 }
 
 static int __remove_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid)
 {
-       LOGD("=== Remove engine info doc");
+       LOGD("@@@ Remove engine info doc");
 
        char *dir_engine_info = NULL;
 
@@ -314,13 +335,13 @@ static int __remove_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid)
 
        FREE(dir_engine_info)
 
-       LOGD("===");
+       LOGD("@@@");
        return 0;
 }
 
 static void __insert_language_from_metadata(xmlNodePtr root, const char *language)
 {
-       LOGD("==== Insert language");
+       LOGD("@@@ Insert language");
        char* voice = NULL;
        char* lang = NULL;
        char* type = NULL;
@@ -354,16 +375,163 @@ static void __insert_language_from_metadata(xmlNodePtr root, const char *languag
                xmlAddChild(voices_node, voice_node);
                voice = strsep(&tmp_lang, ",");
        }
+
+       /* add extra voices */
+       LOGD("Add extra voices");
+       if (NULL != g_voice_info_list) {
+               GSList *iter;
+               voice_info_s *extra_voice = NULL;
+               for (iter = g_voice_info_list ; iter != NULL ; iter = g_slist_next(iter)) {
+                       extra_voice = (voice_info_s*)iter->data;
+                       if (NULL != extra_voice) {
+                               lang = strdup(extra_voice->lang);
+                               type = strdup(extra_voice->type);
+                               LOGD("lang(%s), type(%s)", lang, type);
+
+                               if (NULL != lang) {
+                                       voice_node = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_VOICE);
+                                       xmlSetProp(voice_node, (const xmlChar*)TTS_TAG_ENGINE_VOICE_TYPE, (const xmlChar*)type);
+                                       xmlNodeSetContent(voice_node, (const xmlChar*)lang);
+                                       xmlAddChild(voices_node, voice_node);
+                               }
+
+                               LOGD("Finish to add voice node");
+
+                               if (NULL != lang) {
+                                       free(lang);
+                               }
+                               if (NULL != type) {
+                                       free(type);
+                               }
+                               LOGD("Memory release");
+
+                               if (NULL != extra_voice->lang) {
+                                       free(extra_voice->lang);
+                               }
+                               if (NULL != extra_voice->type) {
+                                       free(extra_voice->type);
+                               }
+                               LOGD("Free extra_voice");
+                               free(extra_voice);
+                               extra_voice = NULL;
+                       }
+               }
+
+               LOGD("Free voice info list");
+               g_slist_free(g_voice_info_list);
+               g_voice_info_list = NULL;
+       }
+
        xmlAddChild(root, voices_node);
 
        FREE(tmp_free)
 }
 
+static int __get_voice_inxml()
+{
+       xmlDocPtr doc = NULL;
+       xmlNodePtr cur = NULL;
+
+       LOGD("TTS voice info xml (%s)", TTS_VOICE_INFO);
+
+       if (0 != access(TTS_VOICE_INFO, F_OK)) {
+               LOGD("There is no extra voice info.");
+               return 0;
+       } else {
+               doc = xmlParseFile(TTS_VOICE_INFO);
+               if (NULL == doc) {
+                       LOGE("Fail to parse file");
+                       return -1;
+               }
+
+               cur = xmlDocGetRootElement(doc);
+               if (NULL == cur) {
+                       LOGE("Empty document");
+                       xmlFreeDoc(doc);
+                       return -1;
+               }
+
+               if (xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_VOICE_BASE)) {
+                       LOGE("root node is NOT %s", TTS_TAG_VOICE_BASE);
+                       xmlFreeDoc(doc);
+                       return -1;
+               }
+
+               cur = cur->xmlChildrenNode;
+               if (NULL == cur) {
+                       LOGE("<tts-voice> child NULL");
+                       xmlFreeDoc(doc);
+                       return -1;
+               }
+
+               xmlChar *attr = NULL;
+               xmlChar *key = NULL;
+//             char lang[16];
+//             char type[16];
+
+               while (NULL != cur) {
+                       if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE_SET)) {
+                               LOGD("<voices>");
+                               xmlNodePtr voice_node = NULL;
+                               voice_node = cur->xmlChildrenNode;
+
+                               while (NULL != voice_node) {
+                                       if (0 == xmlStrcmp(voice_node->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE)) {
+                                               voice_info_s *voice_info = (voice_info_s *)calloc(1, sizeof(voice_info_s));
+                                               if (NULL == voice_info) {
+                                                       LOGE("Fail to allocate memory");
+                                                       xmlFreeDoc(doc);
+                                                       return -1;
+                                               }
+
+                                               LOGD("Get property and keys");
+                                               attr = xmlGetProp(voice_node, (const xmlChar *)TTS_TAG_ENGINE_VOICE_TYPE);
+                                               if (NULL != attr) {
+//                                                     strncpy(type, (char*)attr, strlen((char*)attr));
+                                                       voice_info->type = strdup((char*)attr);
+                                                       LOGD("type(%s)", voice_info->type);
+                                                       xmlFree(attr);
+                                                       attr = NULL;
+                                               } else {
+                                                       LOGD("No voice type");
+                                               }
+
+                                               key = xmlNodeGetContent(voice_node);
+                                               if (NULL != key) {
+//                                                     strncpy(lang, (char*)key, strlen((char*)key));
+                                                       voice_info->lang = strdup((char*)key);
+                                                       LOGD("lang(%s)", voice_info->lang);
+                                                       xmlFree(key);
+                                                       key = NULL;
+                                               } else {
+                                                       LOGD("No voice info");
+                                               }
+
+                                               g_voice_info_list = g_slist_append(g_voice_info_list, voice_info);
+                                       }
+
+                                       voice_node = voice_node->next;
+                               }
+                       } else {
+                               LOGD("Unknown tag (%s)", (const char*)cur->name);
+                       }
+
+                       cur = cur->next;
+               }
+
+               xmlFreeDoc(doc);
+       }
+
+       return 0;
+}
+
 static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *list)
 {
        GList *iter = NULL;
        metadata *md = NULL;
 
+       bool isTextsize = false;
+
        __create_engine_info_xml(pkgid);
 
        xmlNodePtr root = NULL;
@@ -389,6 +557,7 @@ static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *l
                if (NULL != md && NULL != md->key) {
                        LOGD(" - key(%s) value(%s)", md->key, md->value);
                        if (!strcmp(md->key, TTS_METADATA_LANGUAGE)) {
+                               __get_voice_inxml();
                                __insert_language_from_metadata(root, md->value);
                        } else if (!strcmp(md->key, TTS_METADATA_CREDENTIAL_REQUIRED)) {
                                cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_CREDENTIAL);
@@ -402,6 +571,15 @@ static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *l
                                cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_NAME);
                                xmlNodeSetContent(cur, (const xmlChar*)md->value);
                                xmlAddChild(root, cur);
+                       } else if (!strcmp(md->key, TTS_METADATA_TEXT_SIZE)) {
+                               cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_TEXT_SIZE);
+                               xmlNodeSetContent(cur, (const xmlChar*)md->value);
+                               xmlAddChild(root, cur);
+                               isTextsize = true;
+                       } else if (!strcmp(md->key, TTS_METADATA_PITCH_SUPPORT)) {
+                               cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_PITCH_SUPPORT);
+                               xmlNodeSetContent(cur, (const xmlChar*)md->value);
+                               xmlAddChild(root, cur);
                        } else {
                                LOGW("[WARNING] Unknown metadata type");
                        }
@@ -409,6 +587,13 @@ static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *l
                iter = g_list_next(iter);
        }
 
+       if (false == isTextsize) {
+               cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_TEXT_SIZE);
+               xmlNodeSetContent(cur, (const xmlChar*)TTS_MAX_TEXT_SIZE);
+               xmlAddChild(root, cur);
+               LOGD("[DEBUG] Max text size is set as %s.", TTS_MAX_TEXT_SIZE);
+       }
+
        cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_ID);
        xmlNodeSetContent(cur, (const xmlChar*)pkgid);
        xmlAddChild(root, cur);
@@ -536,11 +721,11 @@ int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *
                g_strfreev(query);
 
                if (!users) {
-                       LOGE("Failed to get gum user list");
+                       LOGD("NO users");
                        g_object_unref(gus);
                        gus = NULL;
                        G_FREE(g_user_type)
-                       return -1;
+                       return 0;
                }
 
                /* Make new user list */
@@ -557,6 +742,7 @@ int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *
                        user_type = g_strdup(gum_user_type_to_string(gumut));
                        if (NULL == user_type) {
                                gum_user_service_list_free(users);
+                               G_FREE(home_dir)
                                g_object_unref(gus);
                                gus = NULL;
                                return -1;
@@ -581,6 +767,7 @@ int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *
                                        g_object_unref(gus);
                                        gus = NULL;
                                        G_FREE(user_type)
+                                       G_FREE(home_dir)
                                        return -1;
                                }
                                snprintf(g_dir_config_base, strlen(home_dir) + 14, "%s/share/.voice", home_dir);
@@ -599,15 +786,11 @@ int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *
                                FREE(g_dir_engine_base)
                                FREE(g_dir_engine_info)
 
-                               G_FREE(user_type)
                                G_FREE(home_dir)
-
-                               iter = g_list_next(iter);
-                       } else {
-                               iter = g_list_next(iter);
                        }
 
                        G_FREE(user_type)
+                       iter = g_list_next(iter);
                }
 
                gum_user_service_list_free(users);
@@ -710,6 +893,7 @@ int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList
        uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
        if (globalapp_uid == g_uid) {
                g_user_type = g_strdup("admin");
+               LOGD("[DEBUG] g_user_type: %s (%d)", g_user_type, globalapp_uid);
        } else {
                g_guser = gum_user_get_sync(g_uid, FALSE);
                if (NULL == g_guser) {
@@ -719,6 +903,8 @@ int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList
 
                g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
                g_user_type = g_strdup(gum_user_type_to_string(g_ut));
+
+               LOGD("[DEBUG] g_user_type: %s (%d)", g_user_type, globalapp_uid);
        }
 
        if (NULL == g_user_type) {
@@ -784,11 +970,11 @@ int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList
                g_strfreev(query);
 
                if (!users) {
-                       LOGE("Failed to get gum user list");
+                       LOGD("NO users");
                        g_object_unref(gus);
                        gus = NULL;
                        G_FREE(g_user_type)
-                       return -1;
+                       return 0;
                }
 
                /* Make new user list */