X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=server%2Fttsd_player.c;h=2593de306f24c0602900b19b544f3046afb38177;hb=98e0b4c9d356e00ceb46c24edf20fc2aee1fc940;hp=6caaa4231e9b692e5a38cb001ad5d9e5ff06dec9;hpb=b6dd5399f2665a614fd06c1f9786c9b2cc7e5a67;p=platform%2Fcore%2Fuifw%2Ftts.git diff --git a/server/ttsd_player.c b/server/ttsd_player.c old mode 100755 new mode 100644 index 6caaa42..2593de3 --- a/server/ttsd_player.c +++ b/server/ttsd_player.c @@ -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 @@ -11,135 +11,794 @@ * limitations under the License. */ - -#include -#include -#include -#include -#include +#include #include +#include +#include #include "ttsd_main.h" #include "ttsd_player.h" #include "ttsd_data.h" #include "ttsd_dbus.h" +#include "tts_internal.h" +#include "ttsd_server.h" /* * Internal data structure */ -#define TEMP_FILE_MAX 36 - -typedef struct { - char riff[4]; - int file_size; - char wave[4]; - char fmt[4]; - int header_size; - short sample_format; - short n_channels; - int sample_rate; - int bytes_per_second; - short block_align; - short bits_per_sample; - char data[4]; - int data_size; -} WavHeader; - -typedef struct { - int uid; /** client id */ - MMHandleType player_handle; /** mm player handle */ - int utt_id; /** utt_id of next file */ - ttsp_result_event_e event; /** event of callback */ -} player_s; +typedef enum { + AUDIO_STATE_NONE = 0, + AUDIO_STATE_READY, + AUDIO_STATE_PLAY +} audio_state_e; typedef struct { - int uid; - int utt_id; - ttsp_result_event_e event; - char filename[TEMP_FILE_MAX]; -} user_data_s; + int uid; /** client id */ + app_tts_state_e state; /** client state */ + /* Current utterance information */ + ttse_result_event_e event; /** event of last utterance */ -/* -* static data -*/ + bool is_paused_data; + int idx; + sound_data_s* paused_data; +} player_s; -#define TEMP_FILE_PATH "/tmp" -#define FILE_PATH_SIZE 256 -#define DEFAULT_FILE_SIZE 10 +#define SOUND_BUFFER_LENGTH 2048 +#define FOCUS_SERVER_READY "/tmp/.sound_server_ready" /** player init info */ static bool g_player_init = false; -/** tts engine list */ +/** Client list */ static GList *g_player_list; /** current player information */ static player_s* g_playing_info; -/** player callback function */ -static player_result_callback_func g_result_callback; +/* player state */ +static audio_state_e g_audio_state; + +static ttse_audio_type_e g_audio_type; -/** numbering for temp file */ -static unsigned int g_index; +static int g_sampling_rate; -/** For resume when the 'Paused' state of player after end of play */ -static bool g_pause_info; -static int g_paused_uid; +static audio_out_h g_audio_h; +static sound_stream_info_h g_stream_info_h; + +static int g_focus_watch_id; /* -* Internal Interfaces +* Internal Interfaces */ -player_s* __player_get_item(int uid); +player_s* __player_get_item(int uid) +{ + GList *iter = NULL; + player_s *data = NULL; -int __save_file(const int uid, const int index, const sound_data_s data, char** filename); + if (0 < g_list_length(g_player_list)) { + /* Get a first item */ + iter = g_list_first(g_player_list); -int __set_and_start(player_s* player); + while (NULL != iter) { + /* Get handle data from list */ + data = (player_s*)iter->data; + + /* compare uid */ + if (uid == data->uid) + return data; + + /* Get next item */ + iter = g_list_next(iter); + } + } -int __init_wave_header(WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel); + return NULL; +} -static int msg_callback(int message, void *data, void *user_param) ; +void __player_focus_state_cb(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, + sound_stream_focus_change_reason_e reason_for_change, int sound_behavior, const char *extra_info, void *user_data) +{ + SLOG(LOG_DEBUG, tts_tag(), "@@@ Focus state changed cb"); + if (stream_info != g_stream_info_h) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Invalid stream info handle"); + return; + } + SLOG(LOG_WARN, tts_tag(), "[Player] focus state changed to (%d) with reason(%d) and extra info(%s)", (int)focus_state, (int)reason_for_change, extra_info); -/* -* Player Interfaces + if (AUDIO_STATE_PLAY == g_audio_state && focus_mask == SOUND_STREAM_FOCUS_FOR_PLAYBACK && SOUND_STREAM_FOCUS_STATE_RELEASED == focus_state) { + if (TTSD_MODE_DEFAULT == ttsd_get_mode()) { + g_audio_state = AUDIO_STATE_READY; + + if (NULL == g_playing_info) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player"); + return; + } + + if (APP_STATE_PLAYING == g_playing_info->state) { + int uid = g_playing_info->uid; + + if (0 != ttsd_player_pause(uid)) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to pause the player"); + return; + } + + ttsd_data_set_client_state(uid, APP_STATE_PAUSED); + int pid = ttsd_data_get_pid(uid); + /* send message to client about changing state */ + ttsdc_send_set_state_message(pid, uid, APP_STATE_PAUSED); + } + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player] Ignore focus state cb - mode(%d)", ttsd_get_mode()); + } + } + +/* if (AUDIO_STATE_READY == g_audio_state && focus_mask == SOUND_STREAM_FOCUS_FOR_PLAYBACK && SOUND_STREAM_FOCUS_STATE_ACQUIRED == focus_state) { + if (TTSD_MODE_DEFAULT == ttsd_get_mode()) { + g_audio_state = AUDIO_STATE_PLAY; + + if (NULL == g_playing_info) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player"); + return; + } + + if (APP_STATE_PAUSED == g_playing_info->state) { + int uid = g_playing_info->uid; + + g_audio_state = AUDIO_STATE_PLAY; + if (0 != ttsd_player_resume(uid)) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to resume the player"); + g_audio_state = AUDIO_STATE_READY; + return; + } + + ttsd_data_set_client_state(uid, APP_STATE_PLAYING); + int pid = ttsd_data_get_pid(uid); + ttsdc_send_set_state_message(pid, uid, APP_STATE_PLAYING); + } + + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player] Ignore focus state cb - mode(%d)", ttsd_get_mode()); + } + } */ + SLOG(LOG_DEBUG, tts_tag(), "@@@"); + + return; +} + +void __player_focus_state_watch_cb(int id, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason, + const char *extra_info, void *user_data) +{ + SLOG(LOG_DEBUG, tts_tag(), "@@@ Focus state watch cb"); + + ttsd_mode_e mode = ttsd_get_mode(); + + if (TTSD_MODE_SCREEN_READER != mode && TTSD_MODE_NOTIFICATION != mode) { + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] This is not screen-reader mode and notification mode."); + return; + } + + if (AUDIO_STATE_PLAY == g_audio_state && SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION == reason && + NULL != extra_info && 0 == strncmp(extra_info, "TTSD_MODE_INTERRUPT", strlen(extra_info))) { + /* If the focus is changed by "Interrupt" mode and current players of "SR" and "Noti" modes are on going, please stop the current players. */ + g_audio_state = AUDIO_STATE_READY; + + if (NULL == g_playing_info) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] No current player"); + return; + } + + if (APP_STATE_PLAYING == g_playing_info->state) { + int uid = g_playing_info->uid; + + if (0 != ttsd_server_stop(uid)) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to stop TTS server"); + return; + } + if (0 != ttsd_player_stop(uid)) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to stop the player"); + return; + } + + ttsd_data_set_client_state(uid, APP_STATE_READY); + int pid = ttsd_data_get_pid(uid); + /* send message to client about changing state */ + ttsdc_send_set_state_message(pid, uid, APP_STATE_READY); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player] Not playing state"); + } + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player] This is not Interrupt mode or not playing state."); + } + + return; +} + +static int __create_audio_out(ttse_audio_type_e type, int rate) +{ + int ret = -1; + audio_sample_type_e sample_type; + + if (TTSE_AUDIO_TYPE_RAW_S16 == type) { + sample_type = AUDIO_SAMPLE_TYPE_S16_LE; + } else { + sample_type = AUDIO_SAMPLE_TYPE_U8; + } + + ret = audio_out_create_new(rate, AUDIO_CHANNEL_MONO, sample_type, &g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + g_audio_state = AUDIO_STATE_NONE; + g_audio_h = NULL; + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio"); + return -1; + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Create audio"); + } + + g_audio_type = type; + g_sampling_rate = rate; + + g_audio_state = AUDIO_STATE_READY; + + return 0; +} + +static int __destroy_audio_out() +{ + if (NULL == g_audio_h) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current handle is not valid"); + return -1; + } + + int ret = -1; + ret = audio_out_destroy(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to destroy audio"); + return -1; + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Destroy audio"); + } + + g_audio_type = 0; + g_sampling_rate = 0; + + g_audio_state = AUDIO_STATE_NONE; + g_audio_h = NULL; + + return 0; +} + +static void __end_play_thread(void *data, Ecore_Thread *thread) +{ + SLOG(LOG_ERROR, tts_tag(), "@@@ End thread"); +} -int ttsd_player_init(player_result_callback_func result_cb) +static void __set_policy_for_playing(int volume) { - if (NULL == result_cb) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] invalid parameter"); - return TTSD_ERROR_INVALID_PARAMETER; + /* Set stream info */ + int ret; + ttsd_mode_e mode = ttsd_get_mode(); + if (TTSD_MODE_DEFAULT == mode) { + ret = sound_manager_acquire_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to acquire focus"); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Success to acquire focus (default mode)"); + } + } else if (TTSD_MODE_INTERRUPT == mode) { + ret = sound_manager_acquire_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, "TTSD_MODE_INTERRUPT"); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to acquire focus"); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Success to acquire focus (interrupt mode)"); + } + } + + ret = audio_out_set_sound_stream_info(g_audio_h, g_stream_info_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to set stream info"); + } + + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] set policy for playing"); + + return; +} + +static void __unset_policy_for_playing() +{ + int ret; + ttsd_mode_e mode = ttsd_get_mode(); + /* Unset stream info */ + if (TTSD_MODE_DEFAULT == mode || TTSD_MODE_INTERRUPT == mode) { + sound_stream_focus_state_e state_for_playing = SOUND_STREAM_FOCUS_STATE_ACQUIRED; + ret = sound_manager_get_focus_state(g_stream_info_h, &state_for_playing, NULL); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to get focus state: %d", ret); + } + + if (SOUND_STREAM_FOCUS_STATE_ACQUIRED == state_for_playing) { + if (TTSD_MODE_DEFAULT == mode || TTSD_MODE_INTERRUPT == mode) { + ret = sound_manager_release_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, NULL); + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] release focus (mode: %d)", mode); + } + + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to release focus"); + } + } + } + + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] unset policy for playing"); + + return; +} + +int ttsd_player_check_current_playback_focus(bool *is_current_interrupt) +{ + int ret; + ttsd_mode_e mode = ttsd_get_mode(); + + if (TTSD_MODE_INTERRUPT != mode) { + /* check the current playback focus */ + sound_stream_focus_change_reason_e reason; + int sound_behavior = 0; + char *extra_info = NULL; + + ret = sound_manager_get_current_playback_focus(&reason, &sound_behavior, &extra_info); + + SLOG(LOG_DEBUG, tts_tag(), "[Player] current playback focus: extra_info(%s), reason(%d), sound_behavior(%d)", extra_info, reason, sound_behavior, extra_info); + + if (SOUND_MANAGER_ERROR_NONE == ret && NULL != extra_info && 0 < strlen(extra_info)) { + if (SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION == reason && 0 == strncmp(extra_info, "TTSD_MODE_INTERRUPT", strlen(extra_info))) { + SLOG(LOG_DEBUG, tts_tag(), "[Player] The current focus in Interrupt. Cannot play the requested sound data"); + *is_current_interrupt = true; + + free(extra_info); + extra_info = NULL; + + return TTSD_ERROR_NONE; + } + } + + if (NULL != extra_info) { + free(extra_info); + extra_info = NULL; + } } - g_result_callback = result_cb; + *is_current_interrupt = false; + return TTSD_ERROR_NONE; +} + +static void __play_thread(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; + + int ret = -1; + int len = SOUND_BUFFER_LENGTH; + int idx = 0; + + /* set volume policy as 40% */ + __set_policy_for_playing(40); + while (1) { + if (true == player->is_paused_data) { + /* Resume player */ + sound_data = player->paused_data; + player->paused_data = NULL; + + idx = player->idx; + + player->is_paused_data = false; + player->idx = 0; + + if (NULL == sound_data) { + /* Request unprepare */ + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio"); + } + + g_audio_state = AUDIO_STATE_READY; + + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + return; + } + 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 { + sound_data = NULL; + ret = ttsd_data_get_sound_data(player->uid, &sound_data); + if (0 != ret || NULL == sound_data) { + /* empty queue */ + SLOG(LOG_DEBUG, tts_tag(), "[Player] No sound data. Waiting mode"); + + /* wait for new audio data come */ + while (1) { + usleep(10000); + if (NULL == g_playing_info) { + /* current playing uid is replaced */ + SLOG(LOG_INFO, tts_tag(), "[Player] Finish thread"); + if (AUDIO_STATE_PLAY == g_audio_state) { + /* release audio & recover session */ + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio"); + } + g_audio_state = AUDIO_STATE_READY; + } + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + return; + } else if (0 < ttsd_data_get_sound_data_size(player->uid)) { + /* new audio data come */ + SLOG(LOG_INFO, tts_tag(), "[Player] Resume thread"); + break; + } + + /* If engine is not on processing */ + if (TTSD_SYNTHESIS_CONTROL_DOING != ttsd_get_synth_control()) { + if (AUDIO_STATE_PLAY == g_audio_state) { + /* release audio & recover session */ + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio"); + } + g_audio_state = AUDIO_STATE_READY; + + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + } + } + } + + SLOG(LOG_INFO, tts_tag(), "[Player] Finish to wait for new audio data come"); + + if (AUDIO_STATE_READY == g_audio_state) { + /* set volume policy as 40%, when resume play thread*/ + __set_policy_for_playing(40); + } + + /* resume play thread */ + player->state = APP_STATE_PLAYING; + continue; + } + + /* If wdata's event is 'start', current wdata is first data of engine for synthesis. + * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not. + * When previous wdata's event is 'finish' and current wdata's event is 'finish', + * the player should send utt started event. + */ + if (TTSE_RESULT_EVENT_START == sound_data->event || + (TTSE_RESULT_EVENT_FINISH == player->event && TTSE_RESULT_EVENT_FINISH == sound_data->event)) { + int pid = ttsd_data_get_pid(player->uid); + + if (pid <= 0) { + SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid"); + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + return; + } + + if (0 != ttsdc_send_utt_start_message(pid, player->uid, sound_data->utt_id)) { + SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", + pid, player->uid, sound_data->utt_id); + } + SLOG(LOG_INFO, tts_tag(), "[Player] Start utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id); + } + + /* Save last event to check utterance start */ + player->event = sound_data->event; + idx = 0; + + if (NULL == sound_data->data || 0 >= sound_data->data_size) { + if (TTSE_RESULT_EVENT_FINISH == sound_data->event) { + SLOG(LOG_DEBUG, tts_tag(), "No sound data"); + /* send utterence finish signal */ + int pid = ttsd_data_get_pid(player->uid); + + if (pid <= 0) { + SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid"); + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + return; + } + if (0 != ttsdc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) { + SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", + pid, player->uid, sound_data->utt_id); + } + } + SLOG(LOG_INFO, tts_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id); + ttsd_data_clear_sound_data(player->uid, &sound_data); + continue; + } + } + + if (g_sampling_rate != sound_data->rate || g_audio_type != sound_data->audio_type) { + SLOG(LOG_DEBUG, tts_tag(), "[Player] Change audio handle : org type(%d) org rate(%d)", g_audio_type, g_sampling_rate); + if (NULL != g_audio_h) { + __destroy_audio_out(); + } + + if (0 > __create_audio_out(sound_data->audio_type, sound_data->rate)) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create audio out"); + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + ttsd_data_clear_sound_data(player->uid, &sound_data); + + return; + } + + __set_policy_for_playing(40); + } + + while (APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) { + if ((unsigned int)idx >= sound_data->data_size) + break; + + if ((unsigned int)idx + SOUND_BUFFER_LENGTH > sound_data->data_size) { + len = sound_data->data_size - idx; + } else { + len = SOUND_BUFFER_LENGTH; + } + + if (AUDIO_STATE_READY == g_audio_state) { + /* Request prepare */ + ret = audio_out_prepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to prepare audio : %d", ret); + g_playing_info = NULL; + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + ttsd_data_clear_sound_data(player->uid, &sound_data); + + return; + } + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Prepare audio"); + g_audio_state = AUDIO_STATE_PLAY; + } + + char* temp_data = sound_data->data; + SLOG(LOG_INFO, tts_tag(), "[Player INFO] Before audio_out_write. temp_data(%p), idx(%d), data_idx(%d), uid(%d), utt_id(%d), len(%d)", + temp_data, idx, &temp_data[idx], player->uid, sound_data->utt_id, len); + ret = audio_out_write(g_audio_h, &temp_data[idx], len); + if (0 > ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to audio write - %d", ret); + } else { + idx += len; + SLOG(LOG_INFO, tts_tag(), "[Player INFO] After audio_out_write. temp_data(%p), idx(%d), data_idx(%d), uid(%d), utt_id(%d), len(%d)", + temp_data, idx, &temp_data[idx], player->uid, sound_data->utt_id, len); + } + + if (NULL == g_playing_info && APP_STATE_PAUSED != player->state) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL"); + g_audio_state = AUDIO_STATE_READY; + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + ttsd_data_clear_sound_data(player->uid, &sound_data); + + return; + } + + if (APP_STATE_PAUSED == player->state) { + /* Save data */ + player->paused_data = sound_data; + + player->is_paused_data = true; + player->idx = idx; + + g_audio_state = AUDIO_STATE_READY; + SLOG(LOG_INFO, tts_tag(), "[Player] Stop player thread by pause"); + + /* Request prepare */ + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio"); + } + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + return; + } + } + + if (NULL == g_playing_info && APP_STATE_READY == player->state) { + /* player_stop */ + g_audio_state = AUDIO_STATE_READY; + SLOG(LOG_DEBUG, tts_tag(), "[Player] Stop player thread"); + + /* Request prepare */ + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Unprepare audio"); + } + + ttsd_data_clear_sound_data(player->uid, &sound_data); + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + return; + } + + if ((APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) && + (TTSE_RESULT_EVENT_FINISH == sound_data->event)) { + /* send utterence finish signal */ + int pid = ttsd_data_get_pid(player->uid); + + if (pid <= 0) { + SLOG(LOG_WARN, tts_tag(), "[Send WARNIING] Current player is not valid"); + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + return; + } + + if (0 != ttsdc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) { + SLOG(LOG_ERROR, tts_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", + pid, player->uid, sound_data->utt_id); + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + ttsd_data_clear_sound_data(player->uid, &sound_data); + return; + } + + SLOG(LOG_INFO, tts_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id); + } + + ttsd_data_clear_sound_data(player->uid, &sound_data); + + if (NULL == g_playing_info) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Current player is NULL"); + g_audio_state = AUDIO_STATE_READY; + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } + /* unset volume policy, volume will be 100% */ + __unset_policy_for_playing(); + + return; + } + } +} + +/* +* Player Interfaces +*/ +int ttsd_player_init() +{ g_playing_info = NULL; - - g_index = 1; - g_player_init = true; + g_audio_state = AUDIO_STATE_NONE; + g_audio_h = NULL; - if (TTSD_MODE_DEFAULT == ttsd_get_mode()) { - if (MM_ERROR_NONE != mm_session_init(MM_SESSION_TYPE_EXCLUSIVE)) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_session_init(MM_SESSION_TYPE_EXCLUSIVE)"); + int ret; + + ecore_thread_max_set(1); + + int cnt = 0; + while (1) { + if (0 == access(FOCUS_SERVER_READY, F_OK)) { + SLOG(LOG_ERROR, tts_tag(), "[Player SUCCESS] focus server is available"); + break; } else { - SLOG(LOG_ERROR, get_tag(), "[Player SUCCESS] mm_session_init(MM_SESSION_TYPE_EXCLUSIVE)"); + if (0 == cnt++ % 10) + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] focus server is not available"); + usleep(50000); } } + ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_INFORMATION, __player_focus_state_cb, NULL, &g_stream_info_h); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to create stream info"); + return -1; + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Create stream info"); + } + + /* add sound focus state watch callback */ + ret = sound_manager_add_focus_state_watch_cb(SOUND_STREAM_FOCUS_FOR_PLAYBACK, __player_focus_state_watch_cb, NULL, &g_focus_watch_id); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to add sound focus watch callback"); + sound_manager_destroy_stream_information(g_stream_info_h); + return -1; + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Add sound focus watch callback"); + } + + ecore_thread_max_set(1); + + ret = __create_audio_out(TTSE_AUDIO_TYPE_RAW_S16, 16000); + if (0 != ret) { + sound_manager_destroy_stream_information(g_stream_info_h); + sound_manager_remove_focus_state_watch_cb(g_focus_watch_id); + return -1; + } + + g_player_init = true; + return 0; } int ttsd_player_release(void) { if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized"); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return TTSD_ERROR_OPERATION_FAILED; } + int ret; + + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] @@@@@"); + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] @@@@@"); + + /* The thread should be released */ + int thread_count = ecore_thread_active_get(); + int count = 0; + while (0 < thread_count) { + usleep(10000); + + count++; + if (20 == count) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue."); + break; + } + + thread_count = ecore_thread_active_get(); + } + + SLOG(LOG_DEBUG, tts_tag(), "[Player DEBUG] Thread is released"); + + ret = __destroy_audio_out(); + if (0 != ret) + return -1; + + ret = sound_manager_destroy_stream_information(g_stream_info_h); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to destroy stream info"); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Destroy stream info"); + } + + /* remove focus state watch callback */ + ret = sound_manager_remove_focus_state_watch_cb(g_focus_watch_id); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] Fail to remove the focus state watch cb"); + } else { + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Remove the focus state watch cb"); + } + /* clear g_player_list */ g_playing_info = NULL; g_player_init = false; @@ -147,54 +806,50 @@ int ttsd_player_release(void) return 0; } -int ttsd_player_create_instance(const int uid) +int ttsd_player_create_instance(int uid) { if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } - + /* Check uid is duplicated */ if (NULL != __player_get_item(uid)) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is already registered", uid); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is already registered", uid); return -1; } - int ret = MM_ERROR_NONE; - MMHandleType player_handle; - - ret = mm_player_create(&player_handle); - if (ret != MM_ERROR_NONE || 0 == player_handle) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_create() : %x", ret); - return -2; + player_s* new_client = (player_s*)calloc(1, sizeof(player_s)); + if (NULL == new_client) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Fail to allocate memory"); + return TTSE_ERROR_OUT_OF_MEMORY; } - player_s* new_client = (player_s*)g_malloc0( sizeof(player_s) * 1); - new_client->uid = uid; - new_client->player_handle = player_handle; - new_client->utt_id = -1; - new_client->event = TTSP_RESULT_EVENT_FINISH; + new_client->event = TTSE_RESULT_EVENT_FINISH; + new_client->state = APP_STATE_READY; + new_client->is_paused_data = false; + new_client->idx = 0; + new_client->paused_data = NULL; - SLOG(LOG_DEBUG, get_tag(), "[Player] Create player : uid(%d), handle(%d)", uid, player_handle ); + SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Player] Create player : uid(%d)", uid); g_player_list = g_list_append(g_player_list, new_client); return 0; } - int ttsd_player_destroy_instance(int uid) { if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } player_s* current; current = __player_get_item(uid); if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); return -1; } @@ -203,35 +858,7 @@ int ttsd_player_destroy_instance(int uid) g_playing_info = NULL; } } - - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); - - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state); - - int ret = -1; - /* destroy player */ - switch (player_state) { - case MM_PLAYER_STATE_PLAYING: - case MM_PLAYER_STATE_PAUSED: - case MM_PLAYER_STATE_READY: - ret = mm_player_unrealize(current->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret); - } - /* NO break for destroy */ - - case MM_PLAYER_STATE_NULL: - ret = mm_player_destroy(current->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_destroy() : %x", ret); - } - break; - - default: - break; - } - + GList *iter = NULL; player_s *data = NULL; @@ -246,41 +873,45 @@ int ttsd_player_destroy_instance(int uid) if (NULL != data) { /* compare uid */ if (uid == data->uid) { - g_player_list = g_list_remove_link(g_player_list, iter); - g_free(data); + g_player_list = g_list_remove_link(g_player_list, iter); + free(data); + g_list_free(iter); break; } } - + /* Get next item */ iter = g_list_next(iter); } } - SLOG(LOG_DEBUG, get_tag(), "[PLAYER Success] Destroy instance"); + SLOG(LOG_DEBUG, tts_tag(), "[PLAYER Success] Destroy instance"); return 0; } -int ttsd_player_play(const int uid) +int ttsd_player_play(int uid) { - SLOG(LOG_DEBUG, get_tag(), "[Player] start play : uid(%d)", uid ); - if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } if (NULL != g_playing_info) { if (uid == g_playing_info->uid) { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] uid(%d) has already played", g_playing_info->uid); + SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%d) has already played", g_playing_info->uid); return 0; + } else { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%d)", g_playing_info->uid); + ttsd_player_stop(g_playing_info->uid); } } + SLOG(LOG_DEBUG, tts_tag(), "[Player] start play : uid(%d)", uid); + /* Check sound queue size */ if (0 == ttsd_data_get_sound_data_size(uid)) { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); return -1; } @@ -288,54 +919,28 @@ int ttsd_player_play(const int uid) player_s* current; current = __player_get_item(uid); if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); return -1; } - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); - - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state); - - switch (player_state) { - case MM_PLAYER_STATE_PLAYING: - SLOG(LOG_WARN, get_tag(), "[Player] Current player is playing. Do not start new sound."); - return 0; - - case MM_PLAYER_STATE_PAUSED: - SLOG(LOG_WARN, get_tag(), "[Player] Player is paused. Do not start new sound."); - return -1; - - case MM_PLAYER_STATE_READY: - SLOG(LOG_WARN, get_tag(), "[Player] Player is ready for next play. Do not start new sound."); - return -1; - - case MM_PLAYER_STATE_NULL: - break; + current->state = APP_STATE_PLAYING; - case MM_PLAYER_STATE_NONE: - SLOG(LOG_WARN, get_tag(), "[Player] Player is created. Do not start new sound."); - return -1; + g_playing_info = current; - default: - return -1; - } + SLOG(LOG_INFO, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get()); - int ret; - ret = __set_and_start(current); - if (0 != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to set or start mm_player"); + if (0 < ttsd_data_get_sound_data_size(current->uid)) { + SLOG(LOG_INFO, tts_tag(), "[Player] Run thread"); + ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL); } - SLOG(LOG_DEBUG, get_tag(), "[Player] Started play and wait for played callback : uid(%d)", uid); - return 0; } -int ttsd_player_next_play(int uid) +int ttsd_player_stop(int uid) { if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } @@ -343,70 +948,71 @@ int ttsd_player_next_play(int uid) player_s* current; current = __player_get_item(uid); if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); - g_playing_info = NULL; + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); return -1; } + /* check whether uid is current playing or not */ if (NULL != g_playing_info) { - if (uid != g_playing_info->uid) { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player(%d) is NOT uid(%d)", g_playing_info->uid, uid); - return 0; + if (uid == g_playing_info->uid) { + /* release current playing info */ + g_playing_info = NULL; } } else { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player do NOT exist"); - return -1; + SLOG(LOG_DEBUG, tts_tag(), "[Player] No current playing"); } - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); - - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state); - - int ret = -1; - /* stop player */ - switch (player_state) { - case MM_PLAYER_STATE_PLAYING: - case MM_PLAYER_STATE_PAUSED: - case MM_PLAYER_STATE_READY: - ret = mm_player_unrealize(current->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret); - return -1; - } - break; - - case MM_PLAYER_STATE_NULL: - break; + if (true == current->is_paused_data) { + if (NULL != current->paused_data) { + if (NULL != current->paused_data->data) { + free(current->paused_data->data); + current->paused_data->data = NULL; + } - default: - break; + free(current->paused_data); + current->paused_data = NULL; + } } - /* Check sound queue size */ - if (0 == ttsd_data_get_sound_data_size(uid)) { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); - g_playing_info = NULL; - return -1; - } + current->event = TTSE_RESULT_EVENT_FINISH; + current->state = APP_STATE_READY; + current->is_paused_data = false; + current->idx = 0; + + if (NULL == g_playing_info) { + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); + SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); + + /* The thread should be released */ + int thread_count = ecore_thread_active_get(); + int count = 0; + while (0 < thread_count) { + usleep(10000); + + count++; + if (30 == count) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue."); + break; + } - ret = __set_and_start(current); - if (0 != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to set or start mm_player"); + thread_count = ecore_thread_active_get(); + } + + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); + SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); } - SLOG(LOG_DEBUG, get_tag(), "[Player] Started play and wait for played callback : uid(%d)", uid); + SLOG(LOG_INFO, tts_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid); return 0; } - -int ttsd_player_stop(const int uid) +int ttsd_player_clear(int uid) { - SLOG(LOG_DEBUG, get_tag(), "[Player] stop player : uid(%d)", uid ); - if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } @@ -414,57 +1020,38 @@ int ttsd_player_stop(const int uid) player_s* current; current = __player_get_item(uid); if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); + SECURE_SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); 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 */ - g_playing_info = NULL; + if (true == current->is_paused_data) { + if (NULL != current->paused_data) { + if (NULL != current->paused_data->data) { + free(current->paused_data->data); + current->paused_data->data = NULL; + } + + free(current->paused_data); + current->paused_data = NULL; } - } else { - SLOG(LOG_DEBUG, get_tag(), "[Player] No current playing"); } - current->utt_id = -1; - - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); - - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state); - - int ret = -1; - switch (player_state) { - case MM_PLAYER_STATE_PLAYING: - case MM_PLAYER_STATE_PAUSED: - case MM_PLAYER_STATE_READY: - ret = mm_player_unrealize(current->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret); - return -1; - } - break; - - case MM_PLAYER_STATE_NULL: - break; - - default: - break; - } + current->event = TTSE_RESULT_EVENT_FINISH; + current->state = APP_STATE_READY; + current->is_paused_data = false; + current->idx = 0; - SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid); + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Clear player : uid(%d)", uid); return 0; } -int ttsd_player_pause(const int uid) +int ttsd_player_pause(int uid) { - SLOG(LOG_DEBUG, get_tag(), "[Player] pause player : uid(%d)", uid ); + SLOG(LOG_DEBUG, tts_tag(), "[Player] pause player : uid(%d)", uid); if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } @@ -472,7 +1059,7 @@ int ttsd_player_pause(const int uid) player_s* current; current = __player_get_item(uid); if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid); return -1; } @@ -486,31 +1073,42 @@ int ttsd_player_pause(const int uid) } } - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); + current->state = APP_STATE_PAUSED; - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state); + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); + SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); - int ret = 0; - if (MM_PLAYER_STATE_PLAYING == player_state) { - ret = mm_player_pause(current->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_pause : %x ", ret); + /* The thread should be released */ + int thread_count = ecore_thread_active_get(); + int count = 0; + while (0 < thread_count) { + usleep(10000); + + count++; + if (30 == count) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING!!] Thread is blocked. Player release continue."); + break; } - } else { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player is NOT 'playing'"); + + thread_count = ecore_thread_active_get(); } - + + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); + SLOG(LOG_ERROR, tts_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, tts_tag(), "[Player] @@@@@"); + + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] Pause player : uid(%d)", uid); return 0; } -int ttsd_player_resume(const int uid) +int ttsd_player_resume(int uid) { - SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player : uid(%d)", uid ); + SLOG(LOG_DEBUG, tts_tag(), "[Player] Resume player : uid(%d)", uid); if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } @@ -518,97 +1116,32 @@ int ttsd_player_resume(const int uid) player_s* current; current = __player_get_item(uid); if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); return -1; } /* check current player */ - if (NULL != g_playing_info) + if (NULL != g_playing_info) g_playing_info = NULL; - - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); - - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state); - - int ret = -1; - if (MM_PLAYER_STATE_PAUSED == player_state) { - /* When the 'Paused' state of player after end of play */ - if (g_pause_info == true && g_paused_uid == uid) { - g_playing_info = current; - - g_pause_info = false; - g_paused_uid = -1; - - /* Current state need load and play */ - ret = ttsd_player_next_play(uid); - if (0 != ret) { - SLOG(LOG_ERROR, get_tag(), "[player] Fail to next play in resume function"); - } - } else { - ret = mm_player_resume(current->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_resume() : %d", ret); - return -1; - } else { - SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player"); - } - - g_playing_info = current; - } - } else { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current uid is NOT paused state."); - } - - return 0; -} - -int ttsd_player_get_current_client() -{ - if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); - return -1; - } - - if (NULL != g_playing_info) - return g_playing_info->uid; + current->state = APP_STATE_PLAYING; + g_playing_info = current; - SLOG(LOG_WARN, get_tag(), "[Player WARNING] No current player"); + SLOG(LOG_INFO, tts_tag(), "[Player] Resume to run thread"); + ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL); return 0; } -int ttsd_player_get_current_utterance_id(const int uid) -{ - SLOG(LOG_DEBUG, get_tag(), "[Player] get current utt id : uid(%d)", uid ); - - if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); - return -1; - } - - /* Check uid */ - player_s* current; - current = __player_get_item(uid); - if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); - return -1; - } - - return current->utt_id; -} - int ttsd_player_all_stop() { if (false == g_player_init) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" ); + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } g_playing_info = NULL; - int ret = -1; GList *iter = NULL; player_s *data = NULL; @@ -620,458 +1153,87 @@ int ttsd_player_all_stop() /* Get handle data from list */ data = (player_s*)iter->data; - app_state_e state; + app_tts_state_e state; if (0 > ttsd_data_get_client_state(data->uid, &state)) { - SLOG(LOG_ERROR, get_tag(), "[player ERROR] ttsd_player_all_stop : uid is not valid "); + SLOG(LOG_ERROR, tts_tag(), "[player ERROR] uid(%d) is not valid", data->uid); ttsd_player_destroy_instance(data->uid); iter = g_list_next(iter); continue; } if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) { - /* unrealize player */ - ret = mm_player_unrealize(data->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret); - } - - data->utt_id = -1; - data->event = TTSP_RESULT_EVENT_FINISH; - } - - /* Get next item */ - iter = g_list_next(iter); - } - } - - SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] player all stop!! "); - - return 0; -} - -static Eina_Bool __player_next_play(void *data) -{ - SLOG(LOG_DEBUG, get_tag(), "===== PLAYER NEXT PLAY"); - - int* uid = (int*)data; - - if (NULL == uid) { - SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid is NULL"); - SLOG(LOG_DEBUG, get_tag(), "====="); - SLOG(LOG_DEBUG, get_tag(), " "); - return EINA_FALSE; - } - - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid); - - if (0 != ttsd_player_next_play(*uid)) { - SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to play next"); - } - - free(uid); - - SLOG(LOG_DEBUG, get_tag(), "====="); - SLOG(LOG_DEBUG, get_tag(), " "); - - return EINA_FALSE; -} - -static int msg_callback(int message, void *data, void *user_param) -{ - user_data_s* user_data = NULL; - - user_data = (user_data_s*)user_param; - - if (NULL == user_data) { - SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] user_param is NULL"); - return -1; - } - - int uid = user_data->uid; - int utt_id = user_data->utt_id; - - MMMessageParamType *msg = (MMMessageParamType*)data; - - switch (message) { - case MM_MESSAGE_ERROR: - { - SLOG(LOG_DEBUG, get_tag(), "===== PLAYER ERROR CALLBACK"); - SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] Info : uid(%d), utt id(%d), error file(%s)", uid, utt_id, user_data->filename); - - /* send error info */ - g_result_callback(PLAYER_ERROR, uid, utt_id); - - player_s* current; - current = __player_get_item(uid); - if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid ", uid); - } else { - current->event = TTSP_RESULT_EVENT_FINISH; - } - - if (NULL != user_data) - g_free(user_data); - - /* check current player */ - if (NULL != g_playing_info) { - if (uid == g_playing_info->uid) { - g_playing_info = NULL; - SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid); - } - } - - SLOG(LOG_DEBUG, get_tag(), "====="); - SLOG(LOG_DEBUG, get_tag(), " "); - } - break; /*MM_MESSAGE_ERROR*/ - - case MM_MESSAGE_BEGIN_OF_STREAM: - - break; - - case MM_MESSAGE_END_OF_STREAM: - { - SLOG(LOG_DEBUG, get_tag(), "===== END OF STREAM CALLBACK"); - - if (-1 == remove(user_data->filename)) { - SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to remove temp file", user_data->filename); - } - - /* Check uid */ - player_s* current; - current = __player_get_item(uid); - if (NULL == current) { - SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid", uid); - if (NULL != g_playing_info) { - if (uid == g_playing_info->uid) { - g_playing_info = NULL; - SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid); + data->event = TTSE_RESULT_EVENT_FINISH; + data->state = APP_STATE_READY; + + if (true == data->is_paused_data) { + if (NULL != data->paused_data) { + if (NULL != data->paused_data->data) { + free(data->paused_data->data); + data->paused_data->data = NULL; + } + + free(data->paused_data); + data->paused_data = NULL; } } - SLOG(LOG_DEBUG, get_tag(), "====="); - SLOG(LOG_DEBUG, get_tag(), " "); - return -1; - } - - g_free(user_data); - - int pid = ttsd_data_get_pid(uid); - - /* send utterence finish signal */ - if (TTSP_RESULT_EVENT_FINISH == current->event) { - if (0 == ttsdc_send_utt_finish_message(pid, uid, utt_id)) - SLOG(LOG_DEBUG, get_tag(), "[Send SUCCESS] Send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id); - else - SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id); - } - - /* for sync problem */ - MMPlayerStateType player_state; - mm_player_get_state(current->player_handle, &player_state); - - if (MM_PLAYER_STATE_PAUSED == player_state) { - g_pause_info = true; /* The current state of player is 'Paused' */ - g_paused_uid = uid; /* The current uid when the current state player is 'Paused' */ - } else { - /* play state */ - int* uid_data = (int*) g_malloc0(sizeof(int)); - *uid_data = uid; - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid_data); - - ecore_timer_add(0, __player_next_play, (void*)uid_data); + data->is_paused_data = false; + data->idx = 0; } - SLOG(LOG_DEBUG, get_tag(), "====="); - SLOG(LOG_DEBUG, get_tag(), " "); - } - break; /*MM_MESSAGE_END_OF_STREAM*/ - - case MM_MESSAGE_STATE_CHANGED: - break; - - case MM_MESSAGE_STATE_INTERRUPTED: - if (MM_PLAYER_STATE_PAUSED == msg->state.current) { - - SLOG(LOG_DEBUG, get_tag(), "===== INTERRUPTED CALLBACK"); - - ttsd_data_set_client_state(uid, APP_STATE_PAUSED); - - int pid = ttsd_data_get_pid(uid); - /* send message to client about changing state */ - ttsdc_send_set_state_message (pid, uid, APP_STATE_PAUSED); - - SLOG(LOG_DEBUG, get_tag(), "====="); - SLOG(LOG_DEBUG, get_tag(), " "); - } - break; - - default: - break; - } - - return TRUE; -} - -player_s* __player_get_item(int uid) -{ - 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; - - /* compare uid */ - if (uid == data->uid) - return data; - /* Get next item */ iter = g_list_next(iter); } } - return NULL; -} - -int __save_file(const int uid, const int index, const sound_data_s data, char** filename) -{ - char postfix[5]; - memset(postfix, '\0', 5); - - switch (data.audio_type) { - case TTSP_AUDIO_TYPE_RAW: - case TTSP_AUDIO_TYPE_WAV: - strcpy(postfix, "wav"); - break; - case TTSP_AUDIO_TYPE_MP3: - strcpy(postfix, "mp3"); - break; - case TTSP_AUDIO_TYPE_AMR: - strcpy(postfix, "amr"); - break; - default: - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Audio type(%d) is NOT valid", data.audio_type); - return -1; - } - - /* make filename to save */ - char* temp; - temp = (char*)g_malloc0(sizeof(char) * FILE_PATH_SIZE); - if (NULL == temp) { - SLOG(LOG_ERROR, get_tag(), "[Player Error] make buf is failed"); - return -1; - } - - int ret = snprintf(temp, FILE_PATH_SIZE, "%s/ttstemp%d_%d.%s", TEMP_FILE_PATH, uid, index, postfix); - - if (0 >= ret) { - if (NULL != temp) - g_free(temp); - return -1; - } - - FILE* fp; - fp = fopen(temp, "wb"); - - if (fp == NULL) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] temp file open error"); - if (NULL != temp) - g_free(temp); - return -1; - } - - if (data.audio_type == TTSP_AUDIO_TYPE_RAW) { - WavHeader header; - if (0 != __init_wave_header(&header, data.data_size, data.rate, data.channels)) { - fclose(fp); - if (NULL != temp) - g_free(temp); - return -1; - } - - if (0 >= fwrite(&header, sizeof(WavHeader), 1, fp)) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to write wav header to file"); - fclose(fp); - if (NULL != temp) - g_free(temp); - return -1; - } - } - - int size = fwrite(data.data, data.data_size, 1, fp); - if (size <= 0) { - size = fwrite("0000000000", DEFAULT_FILE_SIZE, 1, fp); - if (size <= 0) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to write date"); - fclose(fp); - if (NULL != temp) - g_free(temp); - return -1; - } - } - - fclose(fp); - *filename = temp; - - SLOG(LOG_DEBUG, get_tag(), " "); - SLOG(LOG_DEBUG, get_tag(), "Filepath : %s ", *filename); - SLOG(LOG_DEBUG, get_tag(), "Header : Data size(%d), Sample rate(%d), Channel(%d) ", data.data_size, data.rate, data.channels); + SLOG(LOG_DEBUG, tts_tag(), "[Player SUCCESS] player all stop!!"); return 0; } -int __init_wave_header (WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel) +int ttsd_player_play_pcm(int uid) { - if (hdr == NULL || sampling_rate <= 0 || channel <= 0) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] __init_wave_header : input parameter invalid"); - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] hdr : %p", hdr); - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] nsample : %d", nsamples); - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] sampling_rate : %", sampling_rate); - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] channel : %", channel); - return TTSD_ERROR_INVALID_PARAMETER; - } - - size_t bytesize = DEFAULT_FILE_SIZE; - - if (0 < nsamples) { - bytesize = nsamples; - } - - /* NOT include \0(NULL) */ - strncpy(hdr->riff, "RIFF", 4); - hdr->file_size = (int)(bytesize + 36); - strncpy(hdr->wave, "WAVE", 4); - strncpy(hdr->fmt, "fmt ", 4); /* fmt + space */ - hdr->header_size = 16; - hdr->sample_format = 1; /* WAVE_FORMAT_PCM */ - hdr->n_channels = channel; - hdr->sample_rate = (int)(sampling_rate); - hdr->bytes_per_second = (int)sampling_rate * sizeof(short); - hdr->block_align = sizeof(short); - hdr->bits_per_sample = sizeof(short)*8; - strncpy(hdr->data, "data", 4); - hdr->data_size = (int)bytesize; - - return 0; -} - -int __set_and_start(player_s* player) -{ - /* get sound data */ - sound_data_s wdata; - if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) { - SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", player->uid); + if (false == g_player_init) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] Not Initialized"); return -1; } - g_index++; - if (10000 <= g_index) { - g_index = 1; - } - - int ret; - - /* make sound file for mmplayer */ - char* sound_file = NULL; - ret = __save_file(player->uid, g_index, wdata, &sound_file); - if (0 != ret || NULL == sound_file) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to make sound file"); - return -1; + if (NULL != g_playing_info) { + if (uid == g_playing_info->uid) { + SLOG(LOG_DEBUG, tts_tag(), "[Player] uid(%d) has already played", g_playing_info->uid); + return 0; + } else { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] stop old player (%d)", g_playing_info->uid); + ttsd_player_stop(g_playing_info->uid); + } } - - user_data_s* user_data = (user_data_s*)g_malloc0(sizeof(user_data_s)); - user_data->uid = player->uid; - user_data->utt_id = wdata.utt_id; - user_data->event = wdata.event; - memset(user_data->filename, 0, TEMP_FILE_MAX); - strncpy( user_data->filename, sound_file, strlen(sound_file) ); - SLOG(LOG_DEBUG, get_tag(), "Info : uid(%d), utt(%d), filename(%s) , event(%d)", - user_data->uid, user_data->utt_id, user_data->filename, user_data->event); - SLOG(LOG_DEBUG, get_tag(), " "); + SLOG(LOG_DEBUG, tts_tag(), "[Player] start play : uid(%d)", uid); - - /* set callback func */ - ret = mm_player_set_message_callback(player->player_handle, msg_callback, (void*)user_data); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_message_callback() : %x ", ret); - return -1; + /* Check sound queue size */ + if (0 == ttsd_data_get_sound_data_size(uid)) { + SLOG(LOG_WARN, tts_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); } - /* set playing info to mm player */ - char* err_attr_name = NULL; - - if (0 != access(sound_file, R_OK)) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to read sound file (%s)", sound_file); - return -1; - } - - ret = mm_player_set_attribute(player->player_handle, &err_attr_name, - "profile_uri", sound_file , strlen(sound_file) + 1, - "sound_volume_type", MM_SOUND_VOLUME_TYPE_MEDIA, - "sound_route", MM_AUDIOROUTE_PLAYBACK_NORMAL, - NULL ); - - if (MM_ERROR_NONE != ret) { - if (NULL != err_attr_name) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_attribute() : msg(%s), result(%x) ", err_attr_name, ret); - } + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SLOG(LOG_ERROR, tts_tag(), "[Player ERROR] uid(%d) is not valid", uid); return -1; } - //if (TTSD_MODE_DEFAULT != ttsd_get_mode()) { - // ret = mm_player_ignore_session(player->player_handle); - // if (MM_ERROR_NONE != ret) { - // SLOG(LOG_WARN, get_tag(), "[Player WARNING] fail mm_player_ignore_session() : %x", ret); - // } - //} - - /* realize and start mm player */ - ret = mm_player_realize(player->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_realize() : %x", ret); - return -2; - } + current->state = APP_STATE_PLAYING; - ret = mm_player_start(player->player_handle); - if (MM_ERROR_NONE != ret) { - SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_start() : %x", ret); + g_playing_info = current; - mm_player_unrealize(player->player_handle); - return -3; - } + SLOG(LOG_INFO, tts_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get()); - /* If wdata's event is 'start', current wdata is first data of engine for synthesis. - * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not. - * When previous wdata's event is 'finish' and current wdata's event is 'finish', - * the player should send utt started event. - */ - if (TTSP_RESULT_EVENT_START == wdata.event || - (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == wdata.event)) { - int pid; - pid = ttsd_data_get_pid(player->uid); - - /* send utterance start message */ - if (0 != ttsdc_send_utt_start_message(pid, player->uid, wdata.utt_id)) { - SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", pid, player->uid, wdata.utt_id); - } - } else { - SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Don't need to send Utterance Start Signal"); + if (0 <= ttsd_data_get_sound_data_size(current->uid)) { + SLOG(LOG_INFO, tts_tag(), "[Player] Run thread"); + ecore_thread_run(__play_thread, __end_play_thread, NULL, NULL); } - g_playing_info = player; - - if (NULL != sound_file) - g_free(sound_file); - if (NULL != wdata.data) - g_free(wdata.data); - return 0; } -