Fix thread unsafety issue in ttsd_player_pause
[platform/core/uifw/tts.git] / server / ttsd_server.c
index f494287..c1b5ab8 100644 (file)
 
 #define CLIENT_CLEAN_UP_TIME 500
 
-
-typedef enum {
-       TTSD_SYNTHESIS_CONTROL_DOING    = 0,
-       TTSD_SYNTHESIS_CONTROL_DONE     = 1,
-       TTSD_SYNTHESIS_CONTROL_EXPIRED  = 2
-} ttsd_synthesis_control_e;
-
 typedef struct {
        int uid;
        int uttid;
@@ -43,9 +36,6 @@ typedef struct {
 /* If current engine exist */
 //static bool  g_is_engine;
 
-/* If engine is running */
-static ttsd_synthesis_control_e        g_synth_control;
-
 static Ecore_Timer* g_check_client_timer = NULL;
 static Ecore_Timer* g_wait_timer = NULL;
 
@@ -53,19 +43,11 @@ static utterance_t g_utt;
 
 static GList *g_proc_list = NULL;
 
-/* Function definitions */
-static int __synthesis(int uid, const char* credential);
+static bool g_is_paused;
 
-static int __server_set_synth_control(ttsd_synthesis_control_e control)
-{
-       g_synth_control = control;
-       return 0;
-}
 
-static ttsd_synthesis_control_e __server_get_synth_control()
-{
-       return g_synth_control;
-}
+/* Function definitions */
+static int __synthesis(int uid, const char* credential);
 
 static Eina_Bool __wait_synthesis(void *data)
 {
@@ -74,11 +56,11 @@ static Eina_Bool __wait_synthesis(void *data)
        int uid = ttsd_data_get_current_playing();
 
        if (uid > 0) {
-               if (TTSD_SYNTHESIS_CONTROL_DOING == __server_get_synth_control()) {
+               if (TTSD_SYNTHESIS_CONTROL_DOING == ttsd_get_synth_control()) {
                        return EINA_TRUE;
                } else {
                        g_wait_timer = NULL;
-                       if (TTSD_SYNTHESIS_CONTROL_DONE == __server_get_synth_control()) {
+                       if (TTSD_SYNTHESIS_CONTROL_DONE == ttsd_get_synth_control()) {
                                /* Start next synthesis */
                                __synthesis(uid, credential);
                        }
@@ -102,8 +84,8 @@ static int __synthesis(int uid, const char* credential)
                }
 
                int pid = ttsd_data_get_pid(uid);
-               char appid[128] = {0, };
-               if (0 != aul_app_get_appid_bypid(pid, appid, sizeof(appid))) {
+               char appid[1024] = {0, };
+               if (0 != aul_app_get_appid_bypid(pid, appid, sizeof(appid) - 1)) {
                        SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get app id");
                }
 
@@ -113,16 +95,7 @@ static int __synthesis(int uid, const char* credential)
 
                        ttsdc_send_set_state_message(pid, uid, APP_STATE_READY);
 
-                       if (NULL != speak_data) {
-                               if (NULL != speak_data->lang)   free(speak_data->lang);
-                               if (NULL != speak_data->text)   free(speak_data->text);
-
-                               speak_data->lang = NULL;
-                               speak_data->text = NULL;
-
-                               free(speak_data);
-                               speak_data = NULL;
-                       }
+                       ttsd_data_clear_speak_data(uid, &speak_data);
 
                        return 0;
                }
@@ -138,12 +111,12 @@ static int __synthesis(int uid, const char* credential)
                SLOG(LOG_INFO, tts_tag(), "-----------------------------------------------------------");
 
                int ret = 0;
-               __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DOING);
+               ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_DOING);
                ret = ttsd_engine_start_synthesis(speak_data->lang, speak_data->vctype, speak_data->text, speak_data->speed, appid, credential, NULL);
                if (0 != ret) {
                        SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] * FAIL to start SYNTHESIS !!!! * ");
 
-                       __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
+                       ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
 
                        ttsd_server_stop(uid);
 
@@ -153,16 +126,9 @@ static int __synthesis(int uid, const char* credential)
                        g_wait_timer = ecore_timer_add(0.05, __wait_synthesis, (void*)credential);
                }
 
-               if (NULL != speak_data) {
-                       if (NULL != speak_data->lang)   free(speak_data->lang);
-                       if (NULL != speak_data->text)   free(speak_data->text);
-
-                       speak_data->lang = NULL;
-                       speak_data->text = NULL;
-
-                       free(speak_data);
-                       speak_data = NULL;
-               }
+               ttsd_data_clear_speak_data(uid, &speak_data);
+       } else {
+               ttsd_data_clear_speak_data(uid, &speak_data);
        }
 
        SLOG(LOG_DEBUG, tts_tag(), "@@@ SYNTHESIS  END");
@@ -181,7 +147,7 @@ int ttsd_send_error(ttse_error_e error, const char* msg)
 
        SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] Error msg from engine, pid(%d), uid(%d), uttid(%d), error(%d), msg(%s)", tmp_pid, uid, uttid, error, (NULL == msg ? "NULL" : msg));
 
-       __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
+       ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
 
        if (0 != ttsd_player_clear(uid))
                SLOG(LOG_WARN, tts_tag(), "[Server] Fail to ttsd_player_stop()");
@@ -224,14 +190,14 @@ int ttsd_send_result(ttse_result_event_e event, const void* data, unsigned int d
 
 
                if (false == ttsd_data_is_uttid_valid(uid, uttid)) {
-                       __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
+                       ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
                        SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] uttid is NOT valid !!!! - uid(%d), uttid(%d)", uid, uttid);
                        SLOG(LOG_DEBUG, tts_tag(), "@@@");
                        return TTSD_ERROR_OPERATION_FAILED;
                }
 
                if (rate <= 0 || audio_type < 0 || audio_type > TTSE_AUDIO_TYPE_MAX) {
-                       __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
+                       ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
                        SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] audio data is invalid");
                        SLOG(LOG_DEBUG, tts_tag(), "@@@");
                        return TTSD_ERROR_INVALID_PARAMETER;
@@ -270,10 +236,25 @@ int ttsd_send_result(ttse_result_event_e event, const void* data, unsigned int d
 
                if (0 != ttsd_data_add_sound_data(uid, temp_sound_data)) {
                        SECURE_SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] Fail to add sound data : uid(%d)", uid);
+                       if (NULL != temp_sound_data->data) {
+                               free(temp_sound_data->data);
+                               temp_sound_data->data = NULL;
+                       }
+
+                       free(temp_sound_data);
+                       temp_sound_data = NULL;
+
+                       return TTSD_ERROR_OPERATION_FAILED;
                }
 
                if (event == TTSE_RESULT_EVENT_FINISH) {
-                       __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
+                       ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE);
+               }
+
+               /* If the app state is paused, do not result to play */
+               if (true == g_is_paused) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[Server DEBUG] tts_pause is called. Do not request to play");
+                       return TTSD_ERROR_NONE;
                }
 
                if (0 != ttsd_player_play(uid)) {
@@ -288,7 +269,7 @@ int ttsd_send_result(ttse_result_event_e event, const void* data, unsigned int d
                }
        } else {
                SLOG(LOG_DEBUG, tts_tag(), "[SERVER] Event : TTSE_RESULT_EVENT_ERROR");
-               __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
+               ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
        }
 
 
@@ -466,7 +447,7 @@ int ttsd_initialize(ttse_request_callback_s *callback)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
+       ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
 
        if (TTSD_MODE_SCREEN_READER == ttsd_get_mode()) {
                ttsd_config_set_screen_reader_callback(__screen_reader_changed_cb);
@@ -510,6 +491,19 @@ int ttsd_finalize()
        return TTSD_ERROR_NONE;
 }
 
+int ttsd_terminate()
+{
+       SLOG(LOG_INFO, tts_tag(), "[Server] Terminate");
+
+       ttsd_terminate_daemon(NULL);
+
+       ttsd_dbus_close_connection();
+       ttsd_network_finalize();
+       ttsd_finalize();
+
+       return TTSD_ERROR_NONE;
+}
+
 /*
 * TTS Server Functions for Client
 */
@@ -528,23 +522,25 @@ int ttsd_server_initialize(int pid, int uid, bool* credential_needed)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       char* appid = NULL;
-       if (0 != app_manager_get_app_id(pid, &appid)) {
-               SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get app id, pid(%d)", pid);
-       }
-       bool is_agreed = false;
-       if (0 != ttsd_engine_check_app_agreed(appid, &is_agreed)) {
-               SLOG(LOG_ERROR, tts_tag(), "Server ERROR] Fail to check app agreed");
+       if (true == *credential_needed) {
+               char* appid = NULL;
+               if (0 != app_manager_get_app_id(pid, &appid)) {
+                       SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get app id, pid(%d)", pid);
+               }
+               bool is_agreed = false;
+               if (0 != ttsd_engine_check_app_agreed(appid, &is_agreed)) {
+                       SLOG(LOG_ERROR, tts_tag(), "Server ERROR] Fail to check app agreed");
+                       if (!appid)
+                               free(appid);
+                       return TTSD_ERROR_OPERATION_FAILED;
+               }
                if (!appid)
                        free(appid);
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-       if (!appid)
-               free(appid);
 
-       if (false == is_agreed) {
-               SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] App is not agreed");
-               return TTSD_ERROR_PERMISSION_DENIED;
+               if (false == is_agreed) {
+                       SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] App is not agreed");
+                       return TTSD_ERROR_PERMISSION_DENIED;
+               }
        }
 
        if (0 != ttsd_data_new_client(pid, uid)) {
@@ -629,8 +625,8 @@ bool __get_client_for_clean_up(int pid, int uid, app_tts_state_e state, void* us
 
        return true;
 #if 0
-       char appid[128] = {0, };
-       if (0 != aul_app_get_appid_bypid(pid, appid, sizeof(appid))) {
+       char appid[1024] = {0, };
+       if (0 != aul_app_get_appid_bypid(pid, appid, sizeof(appid) - 1)) {
                SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get app id");
        }
 
@@ -801,7 +797,7 @@ int ttsd_server_add_queue(int uid, const char* text, const char* lang, int voice
                }
 
                /* Check whether tts-engine is running or not */
-               if (TTSD_SYNTHESIS_CONTROL_DOING == __server_get_synth_control()) {
+               if (TTSD_SYNTHESIS_CONTROL_DOING == ttsd_get_synth_control()) {
                        SLOG(LOG_WARN, tts_tag(), "[Server WARNING] Engine has already been running.");
                } else {
                        __synthesis(uid, credential);
@@ -849,6 +845,20 @@ int ttsd_server_play(int uid, const char* credential)
                }
        }
 
+       /* check the current playback focus */
+       if (TTSD_MODE_INTERRUPT != ttsd_get_mode()) {
+               bool is_current_interrupt = false;
+               if (0 != ttsd_player_check_current_playback_focus(&is_current_interrupt)) {
+                       SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to check the current playback focus");
+               } else {
+                       if (true == is_current_interrupt) {
+                               SLOG(LOG_WARN, tts_tag(), "[Server WARNING] Current playback focus is set on Interrupt mode. Cannot play default, screen reader, and noti modes.");
+                               ttsd_data_clear_data(uid);
+                               return TTSD_ERROR_AUDIO_POLICY_BLOCKED;
+                       }
+               }
+       }
+
        int current_uid = ttsd_data_get_current_playing();
        SLOG(LOG_INFO, tts_tag(), "[Server] playing uid (%d)", current_uid);
 
@@ -895,6 +905,8 @@ int ttsd_server_play(int uid, const char* credential)
        if (APP_STATE_PAUSED == state) {
                SLOG(LOG_DEBUG, tts_tag(), "[Server] uid(%d) is 'Pause' state : resume player", uid);
 
+               g_is_paused = false;
+
                /* Resume player */
                if (0 != ttsd_player_resume(uid)) {
                        SLOG(LOG_WARN, tts_tag(), "[Server WARNING] Fail to ttsd_player_resume()");
@@ -902,7 +914,7 @@ int ttsd_server_play(int uid, const char* credential)
        }
 
        /* Check whether tts-engine is running or not */
-       if (TTSD_SYNTHESIS_CONTROL_DOING == __server_get_synth_control()) {
+       if (TTSD_SYNTHESIS_CONTROL_DOING == ttsd_get_synth_control()) {
                SLOG(LOG_WARN, tts_tag(), "[Server WARNING] Engine has already been running.");
        } else {
                __synthesis(uid, credential);
@@ -922,7 +934,7 @@ int ttsd_server_stop(int uid)
        SLOG(LOG_INFO, tts_tag(), "[Server] server stop, state(%d)", state);
 
        if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
-               if (TTSD_SYNTHESIS_CONTROL_DOING == __server_get_synth_control() && uid == ttsd_data_get_current_playing()) {
+               if (TTSD_SYNTHESIS_CONTROL_DOING == ttsd_get_synth_control() && uid == ttsd_data_get_current_playing()) {
                        SLOG(LOG_DEBUG, tts_tag(), "[Server] TTS-engine is running");
 
                        int ret = 0;
@@ -931,7 +943,7 @@ int ttsd_server_stop(int uid)
                                SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to cancel synthesis : ret(%d)", ret);
                }
 
-               __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
+               ttsd_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED);
 
                if (0 != ttsd_player_clear(uid))
                        SLOG(LOG_WARN, tts_tag(), "[Server] Fail to ttsd_player_stop()");
@@ -941,6 +953,7 @@ int ttsd_server_stop(int uid)
 
        /* Reset all data */
        ttsd_data_clear_data(uid);
+       g_is_paused = false;
 
        return TTSD_ERROR_NONE;
 }
@@ -958,6 +971,8 @@ int ttsd_server_pause(int uid, int* utt_id)
                return TTSD_ERROR_INVALID_STATE;
        }
 
+       g_is_paused = true;
+
        *utt_id = g_utt.uttid;
        SLOG(LOG_INFO, tts_tag(), "[Server] server pause, uid(%d), g_uid(%d), utt_id(%d)", uid, g_utt.uid, *utt_id);
 
@@ -1141,6 +1156,26 @@ int ttsd_server_play_pcm(int uid)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
+       if (APP_STATE_PAUSED == state) {
+               SLOG(LOG_DEBUG, tts_tag(), "[Server] uid(%d) is 'Pause' state : resume player", uid);
+
+               /* Resume player */
+               if (0 != ttsd_player_resume(uid)) {
+                       SLOG(LOG_WARN, tts_tag(), "[Server WARNING] Fail to ttsd_player_resume()");
+               }
+       } else {
+               if (0 != ttsd_player_play_pcm(uid)) {
+                       SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to play pcm sound : uid(%d)", uid);
+
+                       // Change ready state
+                       ttsd_server_stop_pcm(uid);
+
+                       int tmp_pid;
+                       tmp_pid = ttsd_data_get_pid(uid);
+                       ttsdc_send_set_state_message(tmp_pid, uid, APP_STATE_READY);
+               }
+       }
+
        return TTSD_ERROR_NONE;
 }
 
@@ -1154,16 +1189,16 @@ int ttsd_server_stop_pcm(int uid)
 
        SLOG(LOG_INFO, tts_tag(), "[Server] server stop, state(%d)", state);
 
-       if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
-               if (0 != ttsd_player_clear(uid))
-                       SLOG(LOG_WARN, tts_tag(), "[Server] Fail to ttsd_player_stop()");
-
+       if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state || APP_STATE_READY == state) {
                ttsd_data_set_client_state(uid, APP_STATE_READY);
        }
 
        /* Reset all data */
        ttsd_data_clear_data(uid);
 
+       ttsd_player_stop(uid);
+
+
        return TTSD_ERROR_NONE;
 }
 
@@ -1236,16 +1271,17 @@ int ttsd_server_add_pcm(int uid, int event, void* data, int data_size, int audio
                        temp_sound_data = NULL;
                }
 
-               if (0 != ttsd_player_play(uid)) {
+/*             if (0 != ttsd_player_play(uid)) {
                        SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to play sound : uid(%d)", uid);
 
-                       /* Change ready state */
+                       // Change ready state
                        ttsd_server_stop(uid);
 
                        int tmp_pid;
                        tmp_pid = ttsd_data_get_pid(uid);
                        ttsdc_send_set_state_message(tmp_pid, uid, APP_STATE_READY);
                }
+*/
        } else {
                SLOG(LOG_DEBUG, tts_tag(), "[SERVER] Event : TTSE_RESULT_EVENT_ERROR");
        }