Use PlayerThread class to manage current playing client 81/271881/2
authorSuyeon Hwang <stom.hwang@samsung.com>
Mon, 8 Nov 2021 08:09:12 +0000 (17:09 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Tue, 8 Mar 2022 05:25:12 +0000 (14:25 +0900)
Change-Id: I8d32b0570de420485b3c50fea9d28933ba62bf0b
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
server/ttsd_player.cpp

index 286d7e1..a4f0c5e 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "BackgroundVolume.h"
 #include "AudioStream.h"
+#include "PlayerThread.h"
 
 #include "tts_internal.h"
 #include "ttsd_server.h"
@@ -75,6 +76,7 @@ static pthread_cond_t g_play_thread_cond = PTHREAD_COND_INITIALIZER;
 
 static BackgroundVolume* g_background_volume = nullptr;
 static AudioStream* g_audio_stream = nullptr;
+static PlayerThread* g_player_thread = nullptr;
 
 /*
 * Internal Interfaces
@@ -151,21 +153,6 @@ static void __write_buffer_dump_file(const void* buffer, size_t length)
 }
 #endif
 
-static bool __is_player_valid(player_s* player)
-{
-       if (NULL == player || NULL == g_playing_info) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] player is NULL");
-               return false;
-       }
-
-       if (g_playing_info != player || g_playing_info->uid != player->uid) {
-               SLOG(LOG_ERROR, tts_tag(), "[ERROR] player is not current player");
-               return false;
-       }
-
-       return true;
-}
-
 player_s* __player_get_item(unsigned int uid)
 {
        GList *iter = NULL;
@@ -193,18 +180,12 @@ player_s* __player_get_item(unsigned int uid)
 
 static void __focus_release_callback()
 {
-       if (NULL == g_playing_info) {
-               SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player");
+       unsigned int uid = g_player_thread->getCurrentUid();
+       if (APP_STATE_PLAYING != ttsd_data_get_client_state(uid)) {
                return;
        }
 
-       if (APP_STATE_PLAYING != ttsd_data_get_client_state(g_playing_info->uid)) {
-               return;
-       }
-
-       unsigned int uid = g_playing_info->uid;
        ttsd_mode_e mode = ttsd_data_get_mode(uid);
-
        switch (mode) {
        case TTSD_MODE_DEFAULT:
                {
@@ -355,7 +336,7 @@ static int __notify_utterance_completed_event(unsigned int uid, int utt_id)
        return TTSD_ERROR_NONE;
 }
 
-static int __play_sound_data(player_s* player, sound_data_s* sound_data)
+static int __play_sound_data(unsigned int uid, sound_data_s* sound_data)
 {
        if (TTSD_ERROR_NONE != g_audio_stream->setAudioFormat(sound_data->audio_type, sound_data->rate)) {
                SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio out");
@@ -375,7 +356,7 @@ static int __play_sound_data(player_s* player, sound_data_s* sound_data)
 
        unsigned int idx = sound_data->played_data_size;
        while (idx < sound_data->data_size) {
-               app_tts_state_e state = ttsd_data_get_client_state(player->uid);
+               app_tts_state_e state = ttsd_data_get_client_state(uid);
                if (APP_STATE_PLAYING != state && APP_STATE_PAUSED != state) {
                        break;
                }
@@ -389,7 +370,7 @@ static int __play_sound_data(player_s* player, sound_data_s* sound_data)
 
                char* temp_data = sound_data->data;
                SLOG(LOG_INFO, tts_tag(), "[Player INFO] Before audio_out_write. data(%p), data[%d](%p), uid(%u), utt_id(%d), len(%u)",
-                               temp_data, idx, &temp_data[idx], player->uid, sound_data->utt_id, len);
+                               temp_data, idx, &temp_data[idx], uid, sound_data->utt_id, len);
 
 #ifdef BUF_SAVE_MODE
                __write_buffer_dump_file(&temp_data[idx], len);
@@ -407,7 +388,7 @@ static int __play_sound_data(player_s* player, sound_data_s* sound_data)
                        return TTSD_ERROR_INVALID_STATE;
                }
 
-               if (false == __is_player_valid(player)) {
+               if (false == g_player_thread->isCurrentUid(uid)) {
                        return TTSD_ERROR_OPERATION_FAILED;
                }
        }
@@ -415,11 +396,11 @@ static int __play_sound_data(player_s* player, sound_data_s* sound_data)
        return TTSD_ERROR_NONE;
 }
 
-static void __wait_sound_data(player_s* player)
+static void __wait_sound_data(unsigned int uid)
 {
-       while (0 >= ttsd_data_get_sound_data_size(player->uid)) { // 2nd while(1)
+       while (0 >= ttsd_data_get_sound_data_size(uid)) {
                usleep(10000);
-               if (false == __is_player_valid(player)) {
+               if (false == g_player_thread->isCurrentUid(uid)) {
                        return;
                }
 
@@ -439,28 +420,21 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
 {
        SLOG(LOG_DEBUG, tts_tag(), "@@@ Start thread");
 
-       if (NULL == g_playing_info) {
-               SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] No current player");
-               return;
-       }
-
-       player_s* player = g_playing_info;
-       sound_data_s* sound_data = NULL;
-
+       unsigned int uid = g_player_thread->getCurrentUid();
+       sound_data_s* sound_data = nullptr;
        int ret = -1;
        while (1) { // 1st while(1)
-               /* check g_playing_info one more time */
-               if (false == __is_player_valid(player)) {
-                       SLOG(LOG_INFO, tts_tag(), "[Player INFO] Player is not valid");
+               if (false == g_player_thread->isCurrentUid(uid)) {
+                       SLOG(LOG_INFO, tts_tag(), "[Player INFO] uid is not played");
                        g_audio_stream->unprepareAudioOut();
                        __unset_policy_for_playing();
                        return;
                }
 
-               if (ttsd_data_is_paused_data_existing(player->uid)) {
+               if (ttsd_data_is_paused_data_existing(uid)) {
                        /* Resume player */
-                       sound_data = ttsd_data_get_first_sound_data(player->uid);
-                       ttsd_data_set_paused_data_existing(player->uid, false);
+                       sound_data = ttsd_data_get_first_sound_data(uid);
+                       ttsd_data_set_paused_data_existing(uid, false);
 
                        if (NULL == sound_data) {
                                g_audio_stream->unprepareAudioOut();
@@ -472,13 +446,13 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                        SLOG(LOG_INFO, tts_tag(), "[Player] Sound info : id(%d) data(%p) size(%d) audiotype(%d) rate(%d) event(%d)",
                                sound_data->utt_id, sound_data->data, sound_data->data_size, sound_data->audio_type, sound_data->rate, sound_data->event);
                } else { // NO player->is_paused_data
-                       sound_data = ttsd_data_get_first_sound_data(player->uid);
+                       sound_data = ttsd_data_get_first_sound_data(uid);
                        if (nullptr == sound_data) {
                                /* empty queue */
                                SLOG(LOG_ERROR, tts_tag(), "[Player] No sound data. Waiting mode");
 
-                               __wait_sound_data(player);
-                               if (false == __is_player_valid(player)) {
+                               __wait_sound_data(uid);
+                               if (false == g_player_thread->isCurrentUid(uid)) {
                                        SLOG(LOG_INFO, tts_tag(), "[Player] Finish thread");
                                        g_audio_stream->unprepareAudioOut();
                                        __unset_policy_for_playing();
@@ -494,9 +468,9 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                         * When previous wdata's event is 'finish' and current wdata's event is 'finish',
                         * the player should send utt started event.
                         */
-                       ttse_result_event_e last_event = ttsd_data_get_last_sound_result_event(player->uid);
+                       ttse_result_event_e last_event = ttsd_data_get_last_sound_result_event(uid);
                        if (TTSE_RESULT_EVENT_START == sound_data->event || (TTSE_RESULT_EVENT_FINISH == last_event && TTSE_RESULT_EVENT_FINISH == sound_data->event)) {
-                               int ret = __notify_utterance_started_event(player->uid, sound_data->utt_id);
+                               int ret = __notify_utterance_started_event(uid, sound_data->utt_id);
                                if (TTSD_ERROR_INVALID_PARAMETER == ret) {
                                        g_audio_stream->unprepareAudioOut();
                                        __unset_policy_for_playing();
@@ -505,13 +479,13 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                        } // (TTSE_RESULT_EVENT_START == sound_data->event || (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event))
 
                        /* Save last event to check utterance start */
-                       ttsd_data_set_last_sound_result_event(player->uid, sound_data->event);
+                       ttsd_data_set_last_sound_result_event(uid, sound_data->event);
 
                        if (NULL == sound_data->data || 0 >= sound_data->data_size) {
                                ttse_result_event_e event = sound_data->event;
                                int utt_id = sound_data->utt_id;
 
-                               if (TTSD_ERROR_NONE == ttsd_data_pop_sound_data(player->uid)) {
+                               if (TTSD_ERROR_NONE == ttsd_data_pop_sound_data(uid)) {
                                        ttsd_data_destroy_sound_data(sound_data);
                                }
                                sound_data = nullptr;
@@ -520,28 +494,26 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                                        SLOG(LOG_DEBUG, tts_tag(), "No sound data");
                                        __unset_policy_for_playing();
 
-                                       ret = __notify_utterance_completed_event(player->uid, utt_id);
+                                       ret = __notify_utterance_completed_event(uid, utt_id);
                                        if (TTSD_ERROR_INVALID_PARAMETER == ret) {
                                                g_audio_stream->unprepareAudioOut();
                                                return;
                                        }
                                } // TTSE_RESULT_EVENT_FINISH == event
-                               SLOG(LOG_INFO, tts_tag(), "[Player] Event(%d) utterance : uid(%u), uttid(%d)", event, player->uid, utt_id);
+                               SLOG(LOG_INFO, tts_tag(), "[Player] Event(%d) utterance : uid(%u), uttid(%d)", event, uid, utt_id);
                                continue;
                        } // (NULL == sound_data->data || 0 >= sound_data->data_size)
                } // NO player->is_paused_data
 
-               ret = __play_sound_data(player, sound_data);
+               ret = __play_sound_data(uid, sound_data);
                if (TTSD_ERROR_INVALID_STATE == ret) {
-                       SLOG(LOG_DEBUG, tts_tag(), "[Player] Player(%p) is paused, uid(%u)", player, player->uid);
-                       ttsd_data_set_paused_data_existing(player->uid, true);
+                       SLOG(LOG_DEBUG, tts_tag(), "[Player] Uid(%u) is paused", uid);
+                       ttsd_data_set_paused_data_existing(uid, true);
                        g_audio_stream->unprepareAudioOut();
                        __unset_policy_for_playing();
                        return;
                } else if (TTSD_ERROR_NONE != ret) {
-                       SLOG(LOG_ERROR, tts_tag(), "[Player] Fail to play audio data. player(%p), uid(%u)", player, player->uid);
-
-                       g_playing_info = NULL;
+                       SLOG(LOG_ERROR, tts_tag(), "[Player] Fail to play audio data. uid(%u)", uid);
                        g_audio_stream->unprepareAudioOut();
                        __unset_policy_for_playing();
                        return;
@@ -550,13 +522,13 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                ttse_result_event_e event = sound_data->event;
                int utt_id = sound_data->utt_id;
 
-               if (TTSD_ERROR_NONE == ttsd_data_pop_sound_data(player->uid)) {
+               if (TTSD_ERROR_NONE == ttsd_data_pop_sound_data(uid)) {
                        ttsd_data_destroy_sound_data(sound_data);
                }
                sound_data = nullptr;
 
                if (TTSE_RESULT_EVENT_FINISH == event) {
-                       ret = __notify_utterance_completed_event(player->uid, utt_id);
+                       ret = __notify_utterance_completed_event(uid, utt_id);
                        if (TTSD_ERROR_NONE != ret) {
                                g_audio_stream->unprepareAudioOut();
                                __unset_policy_for_playing();
@@ -564,7 +536,7 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                        }
                } // (TTSE_RESULT_EVENT_FINISH == event)
 
-               app_tts_state_e state = ttsd_data_get_client_state(player->uid);
+               app_tts_state_e state = ttsd_data_get_client_state(uid);
                if (APP_STATE_READY == state) {
                        /* player_stop */
                        SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread");
@@ -575,14 +547,6 @@ static void __play_thread_old(void *data, Ecore_Thread *thread)
                        __unset_policy_for_playing();
                        return;
                } // (APP_STATE_READY == state)
-
-               if (NULL == g_playing_info) {
-                       SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL");
-                       g_audio_stream->unprepareAudioOut();
-                       /* unset volume policy, volume will be 100% */
-                       __unset_policy_for_playing();
-                       return;
-               }
        } // end of 1st while(1)
 }
 
@@ -602,9 +566,6 @@ static void __play_thread(void *data, Ecore_Thread *thread)
 
                __play_thread_old(data, thread);
                pthread_mutex_unlock(&g_play_thread_mutex);
-               pthread_mutex_lock(&g_player_control_mutex);
-               g_playing_info = NULL;
-               pthread_mutex_unlock(&g_player_control_mutex);
        }
 }
 
@@ -616,12 +577,10 @@ int ttsd_player_init()
        pthread_mutex_lock(&g_player_control_mutex);
        g_playing_info = NULL;
 
-       ecore_thread_max_set(1);
-
        g_background_volume = new BackgroundVolume(SND_MGR_DUCKING_DURATION);
        g_audio_stream = new AudioStream(__focus_release_callback);
+       g_player_thread = new PlayerThread(nullptr);
 
-       ecore_thread_max_set(1);
        ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL);
 
        g_is_set_policy = false;
@@ -670,6 +629,7 @@ int ttsd_player_release(void)
        /* clear g_player_list */
        g_playing_info = NULL;
        g_player_init = false;
+       g_player_thread->requestStop();
        pthread_cond_broadcast(&g_play_thread_cond);
 
        delete g_audio_stream;
@@ -678,6 +638,9 @@ int ttsd_player_release(void)
        delete g_background_volume;
        g_background_volume = nullptr;
 
+       delete g_player_thread;
+       g_player_thread = nullptr;
+
        pthread_mutex_unlock(&g_player_control_mutex);
 
        return 0;
@@ -778,33 +741,28 @@ int ttsd_player_play(unsigned int uid)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (NULL != g_playing_info) {
-               if (uid == g_playing_info->uid) {
-                       SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%u) has already played", g_playing_info->uid);
+       if (0 > ttsd_data_is_client(uid)) {
+               SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
+               pthread_mutex_unlock(&g_player_control_mutex);
+               return -1;
+       }
+
+       unsigned int currentUid = g_player_thread->getCurrentUid();
+       if (0 < ttsd_data_is_client(currentUid)) {
+               if (uid == currentUid) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%u) has already played", uid);
                        pthread_mutex_unlock(&g_player_control_mutex);
                        return 0;
                } else {
-                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%u)", g_playing_info->uid);
+                       SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%u)", currentUid);
                        pthread_mutex_unlock(&g_player_control_mutex);
-                       ttsd_player_stop(g_playing_info->uid);
+                       ttsd_player_stop(currentUid);
                        pthread_mutex_lock(&g_player_control_mutex);
                }
        }
 
-       SLOG(LOG_DEBUG, tts_tag(), "[Player] start play : uid(%u)", uid);
-
-       /* Check uid */
-       player_s* current;
-       current = __player_get_item(uid);
-       if (NULL == current) {
-               SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
-               pthread_mutex_unlock(&g_player_control_mutex);
-               return -1;
-       }
-
-       g_playing_info = current;
-
-       SLOG(LOG_INFO, tts_tag(), "[Player] Run thread");
+       SLOG(LOG_INFO, tts_tag(), "[Player] start play : uid(%u)", uid);
+       g_player_thread->requestPlay(uid);
        pthread_cond_broadcast(&g_play_thread_cond);
 
        pthread_mutex_unlock(&g_player_control_mutex);
@@ -820,20 +778,15 @@ int ttsd_player_stop(unsigned int uid)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       /* check whether uid is current playing or not */
-       if (NULL != g_playing_info) {
-               if (uid == g_playing_info->uid) {
-                       /* release current playing info */
-                       g_playing_info = NULL;
-               }
-       } else {
-               SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing");
-       }
+       if (uid == g_player_thread->getCurrentUid()) {
+               g_player_thread->requestStop();
+               pthread_cond_broadcast(&g_play_thread_cond);
 
-       if (NULL == g_playing_info) {
                pthread_mutex_lock(&g_play_thread_mutex);
                SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
                pthread_mutex_unlock(&g_play_thread_mutex);
+       } else {
+               SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing");
        }
 
 #ifdef BUF_SAVE_MODE
@@ -841,12 +794,8 @@ int ttsd_player_stop(unsigned int uid)
 #endif
 
        __set_playing_status(false);
-       int ret = ttsd_player_clear(uid);
-       if (0 != ret) {
-               SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to stop player, ret(%d)", ret);
-               pthread_mutex_unlock(&g_player_control_mutex);
-               return ret;
-       }
+       ttsd_data_set_last_sound_result_event(uid, TTSE_RESULT_EVENT_FINISH);
+       ttsd_data_set_paused_data_existing(uid, false);
 
        SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Stop player : uid(%u)", uid);
 
@@ -888,29 +837,16 @@ int ttsd_player_pause(unsigned int uid)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       /* Check uid */
-       player_s* current;
-       current = __player_get_item(uid);
-       if (NULL == current) {
+       if (0 > ttsd_data_is_client(uid)) {
                SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] ttsd_player_pause() : uid(%u) is not valid", uid);
                pthread_mutex_unlock(&g_player_control_mutex);
                return -1;
        }
 
-       /* check whether uid is current playing or not */
-       if (NULL != g_playing_info) {
-               if (uid == g_playing_info->uid) {
-                       /* release current playing info */
-                       SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] release current playing info (%u)", uid);
-                       g_playing_info = NULL;
-               } else {
-                       /* error case */
-               }
-       }
+       if (uid == g_player_thread->getCurrentUid()) {
+               SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] release current playing info (%u)", uid);
+               g_player_thread->requestStop();
 
-       SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] current player (%p), g_playing_info(%p)", current, g_playing_info);
-
-       if (NULL == g_playing_info) {
                pthread_mutex_lock(&g_play_thread_mutex);
                SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get());
                pthread_mutex_unlock(&g_play_thread_mutex);
@@ -938,28 +874,35 @@ int ttsd_player_resume(unsigned int uid)
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       /* Check id */
-       player_s* current;
-       current = __player_get_item(uid);
-       if (NULL == current) {
+       if (0 > ttsd_data_is_client(uid)) {
                SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
                pthread_mutex_unlock(&g_player_control_mutex);
                return -1;
        }
 
-       /* check current player */
-       if (NULL != g_playing_info)
-               g_playing_info = NULL;
-
-       g_playing_info = current;
-
        SLOG(LOG_INFO, tts_tag(), "[Player] Resume to run thread");
+       g_player_thread->requestPlay(uid);
        pthread_cond_broadcast(&g_play_thread_cond);
 
        pthread_mutex_unlock(&g_player_control_mutex);
        return 0;
 }
 
+bool __stop_all_client_callback(int pid, unsigned int uid, app_tts_state_e state, void* user_data)
+{
+       if (0 > ttsd_data_is_client(uid)) {
+               SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%u) is not valid", uid);
+               return true;
+       }
+
+       if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
+               ttsd_data_set_last_sound_result_event(uid, TTSE_RESULT_EVENT_FINISH);
+               ttsd_data_set_paused_data_existing(uid, false);
+       }
+
+       return true;
+}
+
 int ttsd_player_all_stop()
 {
        pthread_mutex_lock(&g_player_control_mutex);
@@ -969,39 +912,8 @@ int ttsd_player_all_stop()
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       g_playing_info = NULL;
-
-       GList *iter = NULL;
-       player_s *data = NULL;
-
-       if (0 < g_list_length(g_player_list)) {
-               /* Get a first item */
-               iter = g_list_first(g_player_list);
-
-               while (NULL != iter) {
-                       /* Get handle data from list */
-                       data = (player_s*)iter->data;
-
-                       app_tts_state_e state = ttsd_data_get_client_state(data->uid);
-                       if (APP_STATE_NONE == state) {
-                               SLOG(LOG_ERROR, tts_tag(), "[player ERROR] uid(%u) is not valid", data->uid);
-                               iter = g_list_next(iter);
-
-                               pthread_mutex_unlock(&g_player_control_mutex);
-                               ttsd_player_destroy_instance(data->uid);
-                               pthread_mutex_lock(&g_player_control_mutex);
-                               continue;
-                       }
-
-                       if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
-                               ttsd_data_set_last_sound_result_event(data->uid, TTSE_RESULT_EVENT_FINISH);
-                               ttsd_data_set_paused_data_existing(data->uid, false);
-                       }
-
-                       /* Get next item */
-                       iter = g_list_next(iter);
-               }
-       }
+       ttsd_data_foreach_clients(__stop_all_client_callback, nullptr);
+       g_player_thread->requestStop();
 
        SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] player all stop!!");