Fix memory leak
[platform/core/uifw/tts.git] / server / ttsd_data.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 88191dd..47e335b
@@ -1,5 +1,5 @@
 /*
-*  Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd All Rights Reserved 
+*  Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  limitations under the License.
 */
 
+#include <list>
+#include <pthread.h>
 #include <vector>
+
 #include "ttsd_main.h"
 #include "ttsd_data.h"
 
 using namespace std;
 
-typedef struct 
+typedef struct
+{
+       char*   lang;
+       int     vctype;
+}used_voice_s;
+
+typedef struct
 {
        int             pid;
        int             uid;
        int             utt_id_stopped;
-       app_state_e     state;
-       
-       std::vector<speak_data_s> m_speak_data; 
-       std::vector<sound_data_s> m_wav_data;
-}app_data_s;
+       app_tts_state_e state;
 
-typedef struct {
-       int pid;
-} setting_app_data_s;
+       std::list<speak_data_s*> m_speak_data;
+       std::list<sound_data_s*> m_wav_data;
+
+       std::list<used_voice_s> m_used_voice;
+}app_data_s;
 
 static vector<app_data_s> g_app_list;
 
-static vector<setting_app_data_s> g_setting_list;
+static pthread_mutex_t g_speak_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t g_sound_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 
-static bool g_mutex_state = false;
+/* If engine is running */
+static ttsd_synthesis_control_e        g_synth_control;
 
 /*
 * functions for debug
 */
-
 int __data_show_list()
 {
        int vsize = g_app_list.size();
 
-       SLOG(LOG_DEBUG, get_tag(), "----- client list -----");
+       SLOG(LOG_DEBUG, tts_tag(), "----- client list -----");
 
-       for (int i=0; i<vsize; i++) {
-               SLOG(LOG_DEBUG, get_tag(), "[%dth] pid(%d), uid(%d), state(%d) \n", i, g_app_list[i].pid, g_app_list[i].uid, g_app_list[i].state );
+       for (int i=0; i < vsize; i++) {
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[%dth] pid(%d), uid(%d), state(%d)", i, g_app_list[i].pid, g_app_list[i].uid, g_app_list[i].state);
        }
 
        if (0 == vsize) {
-               SLOG(LOG_DEBUG, get_tag(), "No Client \n");
+               SLOG(LOG_DEBUG, tts_tag(), "No Client");
        }
 
-       SLOG(LOG_DEBUG, get_tag(), "-----------------------");
-
-       SLOG(LOG_DEBUG, get_tag(), "----- setting client list -----");
+       SLOG(LOG_DEBUG, tts_tag(), "-----------------------");
 
-       vsize = g_setting_list.size();
+       return TTSD_ERROR_NONE;
+}
 
-       for (int i=0; i<vsize; i++) {
-               SLOG(LOG_DEBUG, get_tag(), "[%dth] pid(%d)", i, g_setting_list[i].pid );
+int __data_show_sound_list(int index)
+{
+       SLOG(LOG_DEBUG, tts_tag(), "----- Sound list -----");
+
+       unsigned int i = 0;
+       if (!g_app_list[index].m_wav_data.empty()) {
+               std::list<sound_data_s*>::iterator iter;
+               for (iter = g_app_list[index].m_wav_data.begin(); (NULL != *iter && iter != g_app_list[index].m_wav_data.end()); ++iter) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] data(%p) data size(%d), uttid(%d), type(%d)",
+                                       i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type);
+                       i++;
+               }
        }
 
-       if (0 == vsize) {
-               SLOG(LOG_DEBUG, get_tag(), "No Setting Client");
+       if (i == 0) {
+               SLOG(LOG_DEBUG, tts_tag(), "No Sound Data");
        }
 
-       SLOG(LOG_DEBUG, get_tag(), "--------------------------------");
-
+       SLOG(LOG_DEBUG, tts_tag(), "----------------------");
        return TTSD_ERROR_NONE;
 }
 
-int __data_show_sound_list(int index)
+int __data_show_text_list(int index)
 {
-       SLOG(LOG_DEBUG, get_tag(), "----- Sound list -----");
-       
-       unsigned int i;
-       for (i=0 ; i < g_app_list[index].m_wav_data.size() ; i++) {
-               SLOG(LOG_DEBUG, get_tag(), "[%dth] data size(%ld), uttid(%d), type(%d) \n", 
-                       i+1, g_app_list[index].m_wav_data[i].data_size, g_app_list[index].m_wav_data[i].utt_id, g_app_list[index].m_wav_data[i].audio_type );
+       SLOG(LOG_DEBUG, tts_tag(), "----- Text list -----");
+
+       unsigned int i = 0;
+       if (!g_app_list[index].m_speak_data.empty()) {
+               std::list<speak_data_s*>::iterator iter;
+               for (iter = g_app_list[index].m_speak_data.begin(); (NULL != *iter && iter != g_app_list[index].m_speak_data.end()); ++iter) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)", 
+                                       i + 1, *iter, (*iter)->lang, (*iter)->vctype, (*iter)->speed, (*iter)->utt_id, (*iter)->text);
+                       i++;
+               }
        }
 
-       if (i == 0) {
-               SLOG(LOG_DEBUG, get_tag(), "No Sound Data \n");
+       if (0 == i) {
+               SLOG(LOG_DEBUG, tts_tag(), "No Text Data");
        }
 
-       SLOG(LOG_DEBUG, get_tag(), "----------------------");
+       SLOG(LOG_DEBUG, tts_tag(), "---------------------");
        return TTSD_ERROR_NONE;
 }
 
-int __data_show_text_list(int index)
+int __data_show_used_voice_list(int index)
 {
-       SLOG(LOG_DEBUG, get_tag(), "----- Text list -----");
-
-       unsigned int i;
-       for (i=0 ; i< g_app_list[index].m_speak_data.size() ; i++) {
-               SLOG(LOG_DEBUG, get_tag(), "[%dth] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s) \n", 
-                               i+1, g_app_list[index].m_speak_data[i].lang, g_app_list[index].m_speak_data[i].vctype, g_app_list[index].m_speak_data[i].speed,
-                               g_app_list[index].m_speak_data[i].utt_id, g_app_list[index].m_speak_data[i].text );     
+       SLOG(LOG_DEBUG, tts_tag(), "----- Used voice list -----");
+
+       unsigned int i = 0;
+       if (!g_app_list[index].m_used_voice.empty()) {
+               std::list<used_voice_s>::iterator iter;
+               for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); ++iter) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[%dth] lang(%s), vctype(%d)", i + 1, iter->lang, iter->vctype);
+                       i++;
+               }
        }
 
        if (0 == i) {
-               SLOG(LOG_DEBUG, get_tag(), "No Text Data \n");
+               SLOG(LOG_DEBUG, tts_tag(), "No Voice Data");
        }
 
-       SLOG(LOG_DEBUG, get_tag(), "---------------------");
+       SLOG(LOG_DEBUG, tts_tag(), "---------------------------");
        return TTSD_ERROR_NONE;
 }
 
-
 /*
 * ttsd data functions
 */
 
+int ttsd_set_synth_control(ttsd_synthesis_control_e control)
+{
+       g_synth_control = control;
+       return 0;
+}
+
+ttsd_synthesis_control_e ttsd_get_synth_control()
+{
+       return g_synth_control;
+}
+
 int ttsd_data_new_client(int pid, int uid)
 {
        if( -1 != ttsd_data_is_client(uid) ) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_new_client() : uid is not valid (%d)\n", uid);       
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
@@ -130,11 +163,11 @@ int ttsd_data_new_client(int pid, int uid)
        app.utt_id_stopped = 0;
        app.state = APP_STATE_READY;
 
-       g_app_list.insert( g_app_list.end(), app);
+       g_app_list.insert(g_app_list.end(), app);
 
 #ifdef DATA_DEBUG
        __data_show_list();
-#endif 
+#endif
        return TTSD_ERROR_NONE;
 }
 
@@ -143,14 +176,14 @@ int ttsd_data_delete_client(int uid)
        int index = 0;
 
        index = ttsd_data_is_client(uid);
-       
+
        if (index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_delete_client() : uid is not valid (%d)\n", uid);    
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return -1;
        }
 
        if (0 != ttsd_data_clear_data(uid)) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] fail ttsd_data_clear_data()\n");
+               SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] Fail to clear data");
                return -1;
        }
 
@@ -158,7 +191,7 @@ int ttsd_data_delete_client(int uid)
 
 #ifdef DATA_DEBUG
        __data_show_list();
-#endif 
+#endif
        return TTSD_ERROR_NONE;
 }
 
@@ -166,9 +199,9 @@ int ttsd_data_is_client(int uid)
 {
        int vsize = g_app_list.size();
 
-       for (int i=0; i<vsize; i++) {
+       for (int i = 0; i < vsize; i++) {
                if(g_app_list[i].uid == uid) {
-                       return i;               
+                       return i;
                }
        }
 
@@ -177,7 +210,7 @@ int ttsd_data_is_client(int uid)
 
 int ttsd_data_get_client_count()
 {
-       return g_app_list.size() + g_setting_list.size();
+       return g_app_list.size();
 }
 
 int ttsd_data_get_pid(int uid)
@@ -185,9 +218,9 @@ int ttsd_data_get_pid(int uid)
        int index;
 
        index = ttsd_data_is_client(uid);
-       
+
        if (index < 0)  {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_delete_client() : uid is not valid (%d)\n", uid);    
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
@@ -198,127 +231,345 @@ int ttsd_data_get_speak_data_size(int uid)
 {
        int index = 0;
        index = ttsd_data_is_client(uid);
-       
+
        if (index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_get_speak_data_size() : uid is not valid (%d)\n", uid);      
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
+       /* mutex is locked */
+       pthread_mutex_lock(&g_speak_data_mutex);
        int size = g_app_list[index].m_speak_data.size();
+
+       /* mutex is unlocked */
+       pthread_mutex_unlock(&g_speak_data_mutex);
+
        return size;
 }
 
-int ttsd_data_add_speak_data(int uid, speak_data_s data)
+int ttsd_data_set_used_voice(int uid, const char* lang, int type)
 {
        int index = 0;
        index = ttsd_data_is_client(uid);
 
        if (index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_add_speak_data() : uid is not valid (%d)\n", uid);   
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
-       
-       g_app_list[index].m_speak_data.insert(g_app_list[index].m_speak_data.end(), data);
 
-       if (1 == data.utt_id)
-               g_app_list[index].utt_id_stopped = 0;
+       /* Find voice */
+       std::list<used_voice_s>::iterator iter;
+       if (!g_app_list[index].m_used_voice.empty()) {
+               for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end();++iter) {
+                       if (0 == strcmp(lang, iter->lang) && type == iter->vctype) {
+                               SLOG(LOG_DEBUG, tts_tag(), "[DATA] The voice is already registered (%s)(%d)", lang, type);
+                               return 0;
+                       }
+               }
+       }
+
+       /* Add voice */
+       used_voice_s used_voice;
+       used_voice.lang = strdup(lang);
+       used_voice.vctype = type;
+
+       try {
+               iter = g_app_list[index].m_used_voice.insert(g_app_list[index].m_used_voice.end(), used_voice);
+       } catch (const std::bad_alloc&) {
+               SLOG(LOG_ERROR, tts_tag(), "[DATA][ERROR] Fail to insert m_used_voice (bad_alloc)");
+               return -1;
+       }
+       SLOG(LOG_ERROR, tts_tag(), "[DATA] lang(%s), vctype(%d)", iter->lang, iter->vctype);
 
 #ifdef DATA_DEBUG
-       __data_show_text_list(index);
-#endif 
+       __data_show_used_voice_list(index);
+#endif
+
+       return -1;      /* Need to load voice*/
+}
+
+int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback)
+{
+       int index = 0;
+       index = ttsd_data_is_client(uid);
+
+       if (index < 0) {
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (NULL == callback) {
+               SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] Used voice callback is NULL");
+       }
+
+       /* Find voice */
+       if (!g_app_list[index].m_used_voice.empty()) {
+               std::list<used_voice_s>::iterator iter;
+
+               for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); ++iter) {
+                       if (NULL != callback) {
+                               callback(iter->lang, iter->vctype);
+                       }
+
+                       if (NULL != iter->lang) {
+                               free(iter->lang);
+                               iter->lang = NULL;
+                       }
+               }
+
+               g_app_list[index].m_used_voice.clear();
+       }
+
+#ifdef DATA_DEBUG
+       __data_show_used_voice_list(index);
+#endif
+
        return TTSD_ERROR_NONE;
 }
 
-int ttsd_data_get_speak_data(int uid, speak_data_s* data)
+int ttsd_data_add_speak_data(int uid, speak_data_s* data)
 {
        int index = 0;
        index = ttsd_data_is_client(uid);
 
        if (index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_get_speak_data() : uid is not valid(%d)\n", uid);    
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       if (0 == g_app_list[index].m_speak_data.size()) {
-               SLOG(LOG_WARN, get_tag(), "[DATA WARNING] There is no speak data\n"); 
-               return -1;
+       /* mutex is locked */
+       pthread_mutex_lock(&g_speak_data_mutex);
+
+       std::list<speak_data_s*>::iterator iter;
+
+       try {
+               iter = g_app_list[index].m_speak_data.insert(g_app_list[index].m_speak_data.end(), data);
+       } catch (const std::bad_alloc&) {
+               SLOG(LOG_ERROR, tts_tag(), "[DATA][ERROR] Fail to insert m_speak_data (bad_alloc)");
+               pthread_mutex_unlock(&g_speak_data_mutex);
+
+               return TTSD_ERROR_OUT_OF_MEMORY;
        }
+       SLOG(LOG_ERROR, tts_tag(), "[DATA][%p] utt_id(%d), text(%s), lang(%s), vctype(%d), speed(%d)", 
+                       *iter, (*iter)->utt_id, (*iter)->text, (*iter)->lang, (*iter)->vctype, (*iter)->speed);
+
+       if (1 == data->utt_id)
+               g_app_list[index].utt_id_stopped = 0;
 
-       data->lang = g_strdup(g_app_list[index].m_speak_data[0].lang);
-       data->vctype = g_app_list[index].m_speak_data[0].vctype;
-       data->speed = g_app_list[index].m_speak_data[0].speed;
+#ifdef DATA_DEBUG
+       __data_show_text_list(index);
+#endif
+       pthread_mutex_unlock(&g_speak_data_mutex);
 
-       data->text = g_app_list[index].m_speak_data[0].text;
-       data->utt_id = g_app_list[index].m_speak_data[0].utt_id;
+       return TTSD_ERROR_NONE;
+}
+
+int __get_speak_data(int index, speak_data_s** data)
+{
+       if (0 == g_app_list[index].m_speak_data.size()) {
+#ifdef DATA_DEBUG
+               SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] There is no speak data");
+#endif
+               return -1;
+       }
 
-       g_app_list[index].m_speak_data.erase(g_app_list[index].m_speak_data.begin());
+       if (!g_app_list[index].m_speak_data.empty()) {
+               std::list<speak_data_s*>::iterator iter = g_app_list[index].m_speak_data.begin();
+               *data = *iter;
+               g_app_list[index].m_speak_data.pop_front();
+       }
 
 #ifdef DATA_DEBUG
        __data_show_text_list(index);
-#endif 
+#endif
+       return 0;
+}
+
+int ttsd_data_get_speak_data(int uid, speak_data_s** data)
+{
+       int index = 0;
+       index = ttsd_data_is_client(uid);
+
+       if (index < 0) {
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid(%d)", uid);
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       /* mutex is locked */
+       pthread_mutex_lock(&g_speak_data_mutex);
+
+       if (0 != __get_speak_data(index, data)) {
+               SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] There is no speak data");
+               pthread_mutex_unlock(&g_speak_data_mutex);
+               return -1;
+       }
+
+       pthread_mutex_unlock(&g_speak_data_mutex);
+
        return TTSD_ERROR_NONE;
 }
 
-int ttsd_data_add_sound_data(int uid, sound_data_s data)
+int ttsd_data_add_sound_data(int uid, sound_data_s* data)
 {
        int index = 0;
        index = ttsd_data_is_client(uid);
 
        if(index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_add_sound_data() : uid is not valid (%d)\n", uid);   
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (NULL == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] sound data is NULL");
                return TTSD_ERROR_INVALID_PARAMETER;
        }
+       /* mutex is locked */
+       pthread_mutex_lock(&g_sound_data_mutex);
+
+       std::list<sound_data_s*>::iterator iter;
 
-       g_app_list[index].m_wav_data.insert(g_app_list[index].m_wav_data.end(), data);
+       try {
+               iter = g_app_list[index].m_wav_data.insert(g_app_list[index].m_wav_data.end(), data);
+       } catch (const std::bad_alloc&) {
+               SLOG(LOG_ERROR, tts_tag(), "[DATA][ERROR] Fail to insert m_sound_data (bad_alloc)");
+               pthread_mutex_unlock(&g_sound_data_mutex);
+
+               return TTSD_ERROR_OUT_OF_MEMORY;
+       }
+       SLOG(LOG_ERROR, tts_tag(), "[DATA][%p] utt_id(%d), data(%p) data size(%d), type(%d)", *iter, (*iter)->utt_id, (*iter)->data, (*iter)->data_size, (*iter)->audio_type);
 
 #ifdef DATA_DEBUG
        __data_show_sound_list(index);
-#endif 
+#endif
+
+       /* mutex is unlocked */
+       pthread_mutex_unlock(&g_sound_data_mutex);
+
        return TTSD_ERROR_NONE;
 }
 
-int ttsd_data_get_sound_data(int uid, sound_data_s* data)
+int __get_sound_data(int index, sound_data_s** data)
+{
+       if (0 == g_app_list[index].m_wav_data.size()) {
+#ifdef DATA_DEBUG
+               SLOG(LOG_DEBUG, tts_tag(), "[DATA] There is no wav data");
+#endif
+               return -1;
+       }
+
+       if (!g_app_list[index].m_wav_data.empty()) {
+               std::list<sound_data_s*>::iterator iter = g_app_list[index].m_wav_data.begin();
+               *data = *iter;
+               g_app_list[index].m_wav_data.pop_front();
+       }
+
+#ifdef DATA_DEBUG
+       __data_show_sound_list(index);
+#endif
+       return 0;
+}
+
+int ttsd_data_get_sound_data(int uid, sound_data_s** data)
 {
        int index = 0;
        index = ttsd_data_is_client(uid);
 
+       SLOG(LOG_DEBUG, tts_tag(), "[DATA] sound_data_s: %p", *data);
+
        if (index < 0)  {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_get_sound_data() : uid is not valid (%d)\n", uid);   
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       if (0 == g_app_list[index].m_wav_data.size()) {
-               SLOG(LOG_WARN, get_tag(), "[DATA WARNING] There is no wav data\n"); 
+       /* mutex is locked */
+       pthread_mutex_lock(&g_sound_data_mutex);
+
+       if (0 != __get_sound_data(index, data)) {
+               SLOG(LOG_DEBUG, tts_tag(), "[DATA] There is no wav data");
+               /* mutex is unlocked */
+               pthread_mutex_unlock(&g_sound_data_mutex);
                return -1;
        }
+       /* mutex is unlocked */
+       pthread_mutex_unlock(&g_sound_data_mutex);
 
-       data->data = g_app_list[index].m_wav_data[0].data;
-       data->data_size = g_app_list[index].m_wav_data[0].data_size;
-       data->utt_id = g_app_list[index].m_wav_data[0].utt_id;
-       data->audio_type = g_app_list[index].m_wav_data[0].audio_type;
-       data->rate = g_app_list[index].m_wav_data[0].rate;
-       data->channels = g_app_list[index].m_wav_data[0].channels;
-       data->event = g_app_list[index].m_wav_data[0].event;
-
-       g_app_list[index].m_wav_data.erase(g_app_list[index].m_wav_data.begin());
-
-#ifdef DATA_DEBUG
-       __data_show_sound_list(index);
-#endif 
        return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_get_sound_data_size(int uid)
 {
        int index = 0;
+       int data_size = 0;
        index = ttsd_data_is_client(uid);
 
        if (index < 0)  {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_get_sound_data_size() : uid is not valid (%d)\n", uid);      
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       return g_app_list[index].m_wav_data.size();
+       /* mutex is locked */
+       pthread_mutex_lock(&g_sound_data_mutex);
+       data_size = g_app_list[index].m_wav_data.size();
+
+       /* mutex is unlocked */
+       pthread_mutex_unlock(&g_sound_data_mutex);
+
+       return data_size;
+}
+
+int ttsd_data_clear_speak_data(int uid, speak_data_s** speak_data)
+{
+       pthread_mutex_lock(&g_speak_data_mutex);
+
+       int index = 0;
+       index = ttsd_data_is_client(uid);
+       if (index >= 0) {
+               if (NULL != *speak_data) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)", 
+                                       (*speak_data)->utt_id, (*speak_data)->text, (*speak_data)->lang, (*speak_data)->vctype, (*speak_data)->speed);
+
+                       if (NULL != (*speak_data)->text) {
+                               free((*speak_data)->text);
+                               (*speak_data)->text = NULL;
+                       }
+                       if (NULL != (*speak_data)->lang) {
+                               free((*speak_data)->lang);
+                               (*speak_data)->lang = NULL;
+                       }
+
+                       free(*speak_data);
+                       *speak_data = NULL;
+               }
+       }
+
+       pthread_mutex_unlock(&g_speak_data_mutex);
+
+       return TTSD_ERROR_NONE;
+}
+
+int ttsd_data_clear_sound_data(int uid, sound_data_s** sound_data)
+{
+       pthread_mutex_lock(&g_sound_data_mutex);
+
+       int index = 0;
+       index = ttsd_data_is_client(uid);
+       if (index >= 0) {
+               if (NULL != *sound_data) {
+                       SLOG(LOG_ERROR, tts_tag(), "[DEBUG][%p] event(%d) data(%p) size(%d) rate(%d) utt(%d)", 
+                                       (*sound_data), (*sound_data)->event, (*sound_data)->data, (*sound_data)->data_size, (*sound_data)->rate, (*sound_data)->utt_id);
+
+                       if (NULL != (*sound_data)->data) {
+                               free((*sound_data)->data);
+                               (*sound_data)->data = NULL;
+                       }
+
+                       free(*sound_data);
+                       *sound_data = NULL;
+               }
+       }
+       pthread_mutex_unlock(&g_sound_data_mutex);
+
+       return TTSD_ERROR_NONE;
 }
 
 int ttsd_data_clear_data(int uid)
@@ -327,50 +578,80 @@ int ttsd_data_clear_data(int uid)
 
        index = ttsd_data_is_client(uid);
        if (index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_clear_data() : uid is not valid (%d)\n", uid);       
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
        int removed_last_uttid = -1;
+       speak_data_s* temp_speak = NULL;
+       sound_data_s* temp_sound = NULL;
+
        /* free allocated data */
+       pthread_mutex_lock(&g_speak_data_mutex);
        while(1) {
-               speak_data_s temp;
-               if (0 != ttsd_data_get_speak_data(uid, &temp)) {
+               if (0 != __get_speak_data(index, &temp_speak)) {
                        break;
                }
 
-               if (NULL != temp.text)  free(temp.text);
-               if (NULL != temp.lang)  free(temp.lang);
+               if (NULL != temp_speak) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)", 
+                                       temp_speak->utt_id, temp_speak->text, temp_speak->lang, temp_speak->vctype, temp_speak->speed);
+
+                       if (NULL != temp_speak->text) {
+                               free(temp_speak->text);
+                               temp_speak->text = NULL;
+                       }
+                       if (NULL != temp_speak->lang) {
+                               free(temp_speak->lang);
+                               temp_speak->lang = NULL;
+                       }
+                       removed_last_uttid = temp_speak->utt_id;
 
-               removed_last_uttid = temp.utt_id;
+                       free(temp_speak);
+                       temp_speak = NULL;
+               }
        }
 
        if (-1 != removed_last_uttid) {
                g_app_list[index].utt_id_stopped = removed_last_uttid;
        }
 
+       g_app_list[index].m_speak_data.clear();
+       pthread_mutex_unlock(&g_speak_data_mutex);
+
+       pthread_mutex_lock(&g_sound_data_mutex);
        while(1) {
-               sound_data_s temp;
-               if (0 != ttsd_data_get_sound_data(uid, &temp)) {
+               if (0 != __get_sound_data(index, &temp_sound)) {
                        break;
                }
 
-               if (NULL != temp.data)  free(temp.data);
+               if (NULL != temp_sound) {
+                       SLOG(LOG_ERROR, tts_tag(), "[DEBUG][%p] uid(%d), event(%d) data(%p) size(%d) rate(%d) utt(%d)", 
+                               temp_sound, uid, temp_sound->event, temp_sound->data, temp_sound->data_size, temp_sound->rate, temp_sound->utt_id);
+
+                       if (NULL != temp_sound->data) {
+                               free(temp_sound->data);
+                               temp_sound->data = NULL;
+                       }
+
+                       free(temp_sound);
+                       temp_sound = NULL;
+               }
        }
 
-       g_app_list[index].m_speak_data.clear();
        g_app_list[index].m_wav_data.clear();
+       pthread_mutex_unlock(&g_sound_data_mutex);
 
        return TTSD_ERROR_NONE;
 }
 
-int ttsd_data_get_client_state(int uid, app_state_e* state)
+int ttsd_data_get_client_state(int uid, app_tts_state_e* state)
 {
        int index = 0;
 
        index = ttsd_data_is_client(uid);
        if (index < 0)  {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_get_client_state() : uid is not valid (%d)\n", uid); 
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
@@ -379,30 +660,22 @@ int ttsd_data_get_client_state(int uid, app_state_e* state)
        return TTSD_ERROR_NONE;
 }
 
-int ttsd_data_set_client_state(int uid, app_state_e state)
+int ttsd_data_set_client_state(int uid, app_tts_state_e state)
 {
        int index = 0;
 
        index = ttsd_data_is_client(uid);
        if (index < 0)  {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_set_client_state() : uid is not valid (%d)\n", uid); 
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       if (true == g_mutex_state) {
-               while(true == g_mutex_state)    {
-               }
-       }
-       
-       g_mutex_state = true;
-
        /* The client of playing state of all clients is only one. need to check state. */
        if (APP_STATE_PLAYING == state) {
                int vsize = g_app_list.size();
-               for (int i=0 ; i<vsize ; i++) {
+               for (int i = 0; i < vsize; i++) {
                        if(g_app_list[i].state == APP_STATE_PLAYING) {
-                               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_set_client_state() : a playing client has already existed. \n");     
-                               g_mutex_state = false;
+                               SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] A playing client has already existed.");
                                return -1;
                        }
                }
@@ -410,8 +683,6 @@ int ttsd_data_set_client_state(int uid, app_state_e state)
 
        g_app_list[index].state = state;
 
-       g_mutex_state = false;
-
        return TTSD_ERROR_NONE;
 }
 
@@ -419,32 +690,53 @@ int ttsd_data_get_current_playing()
 {
        int vsize = g_app_list.size();
 
-       for (int i=0; i<vsize; i++) {
+       for (int i = 0; i < vsize; i++) {
                if (APP_STATE_PLAYING == g_app_list[i].state) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[DATA] uid(%d) is playing", g_app_list[i].uid);
                        return g_app_list[i].uid;
                }
        }
 
-       SLOG(LOG_DEBUG, get_tag(), "[DATA] NO CURRENT PLAYING !!");     
-
        return -1;
 }
 
 int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data)
 {
        if (NULL == callback) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] input data is NULL!!");
+               SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] input data is NULL!!");
                return -1;
        }
 
+#ifdef DATA_DEBUG
+       __data_show_list();
+#endif
+
+       /* Copy app info */
+       vector<app_data_s> temp_app_list;
        int vsize = g_app_list.size();
 
-       for (int i=0; i<vsize; i++) {
-               if (false == callback(g_app_list[i].pid, g_app_list[i].uid, g_app_list[i].state, user_data)) {
+       int i = 0;
+       for (i = 0;i < vsize;i++) {
+               app_data_s app;
+               app.pid = g_app_list[i].pid;
+               app.uid = g_app_list[i].uid;
+               app.utt_id_stopped = 0;
+               app.state = g_app_list[i].state;
+
+               temp_app_list.insert(temp_app_list.end(), app);
+       }
+
+       for (i = 0;i < vsize;i++) {
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[%dth] pid(%d), uid(%d), state(%d)", i, temp_app_list[i].pid, temp_app_list[i].uid, temp_app_list[i].state);
+               if (false == callback(temp_app_list[i].pid, temp_app_list[i].uid, temp_app_list[i].state, user_data)) {
                        break;
                }
        }
-       
+
+       for (i = 0;i < vsize;i++) {
+               temp_app_list.erase(temp_app_list.begin());
+       }
+
        return 0;
 }
 
@@ -454,8 +746,8 @@ bool ttsd_data_is_uttid_valid(int uid, int uttid)
 
        index = ttsd_data_is_client(uid);
        if (index < 0)  {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] ttsd_data_set_client_state() : uid is not valid (%d)\n", uid); 
-               return TTSD_ERROR_INVALID_PARAMETER;
+               SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
+               return false;
        }
 
        if (uttid < g_app_list[index].utt_id_stopped)
@@ -468,67 +760,27 @@ int ttsd_data_is_current_playing()
 {
        int vsize = g_app_list.size();
 
-       for (int i=0; i<vsize; i++) {
+       for (int i = 0; i < vsize; i++) {
                if(g_app_list[i].state == APP_STATE_PLAYING) {
-                       return g_app_list[i].uid;               
+                       return g_app_list[i].uid;
                }
        }
 
        return -1;
 }
 
-/*
-* setting data
-*/
-
-int ttsd_setting_data_add(int pid)
-{
-       if (-1 != ttsd_setting_data_is_setting(pid)) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] pid(%d) is not valid", pid);   
-               return TTSD_ERROR_INVALID_PARAMETER;
-       }
-
-       setting_app_data_s setting_app;
-       setting_app.pid = pid;
-       
-       g_setting_list.insert(g_setting_list.end(), setting_app);
-
-#ifdef DATA_DEBUG
-       __data_show_list();
-#endif 
-       return TTSD_ERROR_NONE;
-
-}
-
-int ttsd_setting_data_delete(int pid)
+int ttsd_data_get_same_pid_client_count(int pid)
 {
-       int index = 0;
-
-       index = ttsd_setting_data_is_setting(pid);
-
-       if (index < 0) {
-               SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] uid is not valid (%d)", pid);  
-               return -1;
-       }
-
-       g_setting_list.erase(g_setting_list.begin()+index);
-
-#ifdef DATA_DEBUG
-       __data_show_list();
-#endif 
-       return TTSD_ERROR_NONE;
-}
+       int vsize = g_app_list.size();
+       int number = 0;
 
-int ttsd_setting_data_is_setting(int pid)
-{
-       int vsize = g_setting_list.size();
-       for (int i=0; i<vsize; i++) {
-               if(g_setting_list[i].pid == pid) {
-                       return i;               
+       for (int i = 0;i < vsize;i++) {
+               if(g_app_list[i].pid == pid) {
+                       number++;
                }
        }
-       
-       return -1;
+
+       return number;
 }
 
 int ttsd_data_save_error_log(int uid, FILE* fp)
@@ -538,42 +790,56 @@ int ttsd_data_save_error_log(int uid, FILE* fp)
        /* pid */
        pid = ttsd_data_get_pid(uid);
        if (0 > pid) {
-               SLOG(LOG_ERROR, get_tag(), "[ERROR] Fail to get pid");
+               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get pid");
        } else {
-               fprintf(fp, "pid - %d\n", pid);
+               fprintf(fp, "pid - %d", pid);
        }
        /* app state */
-       app_state_e state;
+       app_tts_state_e state;
        ret = ttsd_data_get_client_state(uid, &state);
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[ERROR] Fail to get app state");
+               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get app state");
        } else {
-               fprintf(fp, "app state - %d\n", state);
+               fprintf(fp, "app state - %d", state);
        }
 
        int index = 0;
        unsigned int i;
 
        index = ttsd_data_is_client(uid);
+       if (0 > index) {
+               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid client");
+               return -1;
+       }
 
        /* get sound data */
-       fprintf(fp, "----- Sound list -----\n");
-       
-       for (i=0 ; i < g_app_list[index].m_wav_data.size() ; i++) {
-               fprintf(fp, "[%dth] data size(%ld), uttid(%d), type(%d) \n", 
-                       i+1, g_app_list[index].m_wav_data[i].data_size, g_app_list[index].m_wav_data[i].utt_id, g_app_list[index].m_wav_data[i].audio_type );
-       }
-       fprintf(fp, "----------------------\n");
-       
-       /* get speck data */
-       fprintf(fp, "----- Text list -----\n");
+       fprintf(fp, "----- Sound list -----");
+
+       i = 0;
+       if (!g_app_list[index].m_wav_data.empty()) {
+               std::list<sound_data_s*>::iterator iter;
+               for (iter = g_app_list[index].m_wav_data.begin(); (NULL != *iter && iter != g_app_list[index].m_wav_data.end()); ++iter) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] data(%p) data size(%d), uttid(%d), type(%d)",
+                                       i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type);
+                       i++;
+               }
+       }
 
-       for (i=0 ; i< g_app_list[index].m_speak_data.size() ; i++) {
-               fprintf(fp, "[%dth] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s) \n", 
-                               i+1, g_app_list[index].m_speak_data[i].lang, g_app_list[index].m_speak_data[i].vctype, g_app_list[index].m_speak_data[i].speed,
-                               g_app_list[index].m_speak_data[i].utt_id, g_app_list[index].m_speak_data[i].text );     
+       fprintf(fp, "----------------------");
+
+       /* get speck data */
+       fprintf(fp, "----- Text list -----");
+
+       i = 0;
+       if (!g_app_list[index].m_speak_data.empty()) {
+               std::list<speak_data_s*>::iterator iter_speak;
+               for (iter_speak = g_app_list[index].m_speak_data.begin(); (NULL != *iter_speak && iter_speak != g_app_list[index].m_speak_data.end()); ++iter_speak) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)",
+                                       i, *iter_speak, (*iter_speak)->lang, (*iter_speak)->vctype, (*iter_speak)->speed, (*iter_speak)->utt_id, (*iter_speak)->text);
+                       i++;
+               }
        }
        fprintf(fp, "---------------------");
-       
+
        return 0;
-}
\ No newline at end of file
+}