From: @CHENG <2393524978@qq.com> Date: Tue, 10 Sep 2024 09:59:29 +0000 (+0800) Subject: [Z5_CIRCLE_240_240] voicechat X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=6ae21d5bec9036d4a0d5a43465b0bec37e5a1a0e;p=mirrors%2FASR3603_Z5.git [Z5_CIRCLE_240_240] voicechat --- diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/primary_function/list/ICON_VOICECHAT_LIST.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/primary_function/list/ICON_VOICECHAT_LIST.png new file mode 100644 index 00000000..03ee4e55 Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/primary_function/list/ICON_VOICECHAT_LIST.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ANIM_VOICECHAT_LISTENING.gif b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ANIM_VOICECHAT_LISTENING.gif new file mode 100644 index 00000000..ca881c62 Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ANIM_VOICECHAT_LISTENING.gif differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ANIM_VOICECHAT_THINKING.gif b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ANIM_VOICECHAT_THINKING.gif new file mode 100644 index 00000000..8bde1339 Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ANIM_VOICECHAT_THINKING.gif differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_CANCEL_BUTTON.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_CANCEL_BUTTON.png new file mode 100644 index 00000000..de9d638e Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_CANCEL_BUTTON.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_DEFAULT.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_DEFAULT.png new file mode 100644 index 00000000..2ecf59bf Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_DEFAULT.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_PROMPT.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_PROMPT.png new file mode 100644 index 00000000..df210cec Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_PROMPT.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_DEFAULT.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_DEFAULT.png new file mode 100644 index 00000000..2f8f4523 Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_DEFAULT.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_PRESSED.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_PRESSED.png new file mode 100644 index 00000000..80989d0a Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_PRESSED.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_THINKING.png b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_THINKING.png new file mode 100644 index 00000000..b5d28b80 Binary files /dev/null and b/2.sdk/project/Z5_CIRCLE_240_240/gui/lv_watch/resource/png/voice_chat/ICON_VOICECHAT_THINKING.png differ diff --git a/2.sdk/project/Z5_CIRCLE_240_240/product/craneg_modem/config/watch/lv_watch_conf_CUSTOM.h b/2.sdk/project/Z5_CIRCLE_240_240/product/craneg_modem/config/watch/lv_watch_conf_CUSTOM.h index a75cf379..54e587c6 100644 --- a/2.sdk/project/Z5_CIRCLE_240_240/product/craneg_modem/config/watch/lv_watch_conf_CUSTOM.h +++ b/2.sdk/project/Z5_CIRCLE_240_240/product/craneg_modem/config/watch/lv_watch_conf_CUSTOM.h @@ -223,6 +223,9 @@ #define __MMI_SEDENTARY_REMIND_SUPPORT__ +#define __MMI_CUSTOM_VOICECHAT_SUPPORT__ + + #endif diff --git a/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c b/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c index be95cc8e..b66aeadb 100644 --- a/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c +++ b/2.sdk/sdk/gui/lv_watch/framework/language/lang_ch.c @@ -985,6 +985,7 @@ const void * lang_text_ch[] = { "连接超时\n请重新开始对话", // WATCH_TEXT_ID_AIGC_CONNECT_TIMEOUT, "继续对话", // WATCH_TEXT_ID_AIGC_CONTINUE, "设备温度过高\n请暂缓使用", // WATCH_TEXT_ID_CHIP_HIGH_TEMPERATURE, + "Voice chat", // WATCH_TEXT_ID_VOICECHAT, //CHENG_MODIFY "确认是否跌倒?", // WATCH_TEXT_ID_falldown, "确认是否删除", diff --git a/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c b/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c index 6be1b315..bc4b99fd 100644 --- a/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c +++ b/2.sdk/sdk/gui/lv_watch/framework/language/lang_en.c @@ -986,6 +986,7 @@ const void * lang_text_en[] = { "Timeout\nPlease try again", // WATCH_TEXT_ID_AIGC_CONNECT_TIMEOUT, "Continue", // WATCH_TEXT_ID_AIGC_CONTINUE, "Temperature too high\nPlease suspended use", // WATCH_TEXT_ID_CHIP_HIGH_TEMPERATURE, + "Voice chat", // WATCH_TEXT_ID_VOICECHAT, //CHENG_MODIFY "Confirm a fall", "Confirm deletion", diff --git a/2.sdk/sdk/gui/lv_watch/include/ui_activity_id.h b/2.sdk/sdk/gui/lv_watch/include/ui_activity_id.h index bddec1e6..bac5866d 100644 --- a/2.sdk/sdk/gui/lv_watch/include/ui_activity_id.h +++ b/2.sdk/sdk/gui/lv_watch/include/ui_activity_id.h @@ -226,6 +226,12 @@ enum ACT_ID_AIGC_RECORDING, ACT_ID_AIGC_SENDING, #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + ACT_ID_VOICECHAT_MAIN, + ACT_ID_VOICECHAT_WAITTING, + ACT_ID_VOICECHAT_RECORDING, + ACT_ID_VOICECHAT_SENDING, +#endif #ifdef __MMI_CUSTOM_BEI_KE_RUI_SHENG__ ACT_ID_AI_TALK, ACT_ID_AI_TALK_RECORDING, diff --git a/2.sdk/sdk/gui/lv_watch/include/ui_textid.h b/2.sdk/sdk/gui/lv_watch/include/ui_textid.h index 41e755f2..c86b23a7 100644 --- a/2.sdk/sdk/gui/lv_watch/include/ui_textid.h +++ b/2.sdk/sdk/gui/lv_watch/include/ui_textid.h @@ -993,6 +993,7 @@ enum WATCH_TEXT_ID_AIGC_CONNECT_TIMEOUT, /* "连接超时\n请重新开始对话" "Timeout\nPlease try again" */ WATCH_TEXT_ID_AIGC_CONTINUE, /* "继续对话" "Continue" */ WATCH_TEXT_ID_CHIP_HIGH_TEMPERATURE, /* "设备温度过高\n请暂缓使用" "Temperature too high\nPlease suspended use" */ + WATCH_TEXT_ID_VOICECHAT, /* "Voice chat" "Voice chat" */ //CHENG_MODIFY WATCH_TEXT_ID_FALLDWON, /*确认是否跌倒*/ WATCH_TEXT_ID_CONFIRM_DELETE, /*确认是否删除*/ diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.c b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.c index ba559878..dd404466 100644 --- a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.c +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.c @@ -22,6 +22,10 @@ #include "mmi_aigc_ui.c" #include "mmi_aigc_data.c" #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ +#include "mmi_voicechat_ui.c" +#include "mmi_voicechat_data.c" +#endif #ifdef __MMI_CUSTOM_BEI_KE_RUI_SHENG__ #include "bei_ke_rui_sheng.c" diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.h b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.h index c504d787..f3e59fb1 100644 --- a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.h +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/custom_function.h @@ -34,6 +34,10 @@ extern "C" { #include "mmi_aigc_ui.h" #include "mmi_aigc_data.h" #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ +#include "mmi_voicechat_ui.h" +#include "mmi_voicechat_data.h" +#endif #ifdef __MMI_CUSTOM_BEI_KE_RUI_SHENG__ #include "bei_ke_rui_sheng.h" diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_data.c b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_data.c new file mode 100644 index 00000000..e0f1673b --- /dev/null +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_data.c @@ -0,0 +1,951 @@ + + + +#include "lv_watch.h" + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + +//static void mmi_voicechat_recv_trans_text_data_process(void * data_ptr, uint32_t data_len); +//static void mmi_voicechat_recv_chat_text_data_process(void * data_ptr, uint32_t data_len); +//static void mmi_voicechat_recv_tts_audio_data_process(void * data_ptr, uint32_t data_len); + +static void mmi_voicechat_send_trans_start_data_process(void * data_ptr, uint32_t data_len); +static void mmi_voicechat_send_trans_audio_data_process(void * data_ptr, uint32_t data_len); +static void mmi_voicechat_send_trans_stop_data_process(void * data_ptr, uint32_t data_len); +static void mmi_voicechat_send_chat_text_data_process(void * data_ptr, uint32_t data_len); +//static void mmi_voicechat_send_tts_start_data_process(void * data_ptr, uint32_t data_len); +//static void mmi_voicechat_send_tts_stop_data_process(void * data_ptr, uint32_t data_len); +static void mmi_voicechat_send_tts_text_data_process(void * data_ptr, uint32_t data_len); + + + +#if 0 +// recv task +static TASK_HANDLE * s_voicechat_data_recv_task_id = NULL; + +static void mmi_voicechat_data_recv_task_msg_send(MMI_VOICECHAT_DATA_RECV_MSG_ID_E msg_id, void * param, uint32_t param_size) +{ + printf("[@CHENG_DEBUG][%s][%d]: msg_id=%d\n",__FUNCTION__,__LINE__, msg_id); + + if(NULL != s_voicechat_data_recv_task_id) + { + if((MMI_VOICECHAT_DATA_RECV_TASK_MSG_QUEUE_SIZE - 1) < Hal_Get_Message_Count(s_voicechat_data_recv_task_id)) + { + printf("[@CHENG_DEBUG][%s][%d]: msg queue full\n",__FUNCTION__,__LINE__); + return; + } + + printf("[@CHENG_DEBUG][%s][%d]: \n",__FUNCTION__,__LINE__); + + void * temp_ptr = NULL; + if(NULL != param && 0 != param_size) + { + temp_ptr = lv_mem_alloc(param_size + 1); + if(NULL == temp_ptr) + { + printf("[@CHENG_DEBUG][%s][%d]: memory alloc fail\n", __FUNCTION__, __LINE__); + return; + } + _lv_memset_00(temp_ptr, param_size + 1); + _lv_memcpy(temp_ptr, param, param_size); + } + + mmi_voicechat_data_task_msg_t * msg = Hal_Mem_Alloc(sizeof(mmi_voicechat_data_task_msg_t)); + msg->cmd_type = msg_id; + msg->cmd_param = temp_ptr; + msg->param_size = param_size; + + Hal_Send_Message((TASK_ID)s_voicechat_data_recv_task_id, (void *)msg); + } +} + +static void mm_voicechat_data_recv_task_handle(void * param) +{ + mmi_voicechat_data_task_msg_t * msg = (mmi_voicechat_data_task_msg_t *)param; + MMI_VOICECHAT_DATA_RECV_MSG_ID_E msg_id = msg->cmd_type; + void * msg_param = msg->cmd_param; + uint32_t param_size = msg->param_size; + + printf("[@CHENG_DEBUG][%s][%d]: msg_id=%d\n",__FUNCTION__,__LINE__, msg_id); + switch(msg_id) + { + case MMI_VOICECHAT_MSG_TRANS_TEXT_RECV: + mmi_voicechat_recv_trans_text_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_CHAT_TEXT_RECV: + mmi_voicechat_recv_chat_text_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_TTS_AUDIO_RECV: + mmi_voicechat_recv_tts_audio_data_process(msg_param, param_size); + break; + + default: + break; + } +} + +static void mm_voicechat_data_recv_task_entry(void * para) +{ + while(s_voicechat_data_recv_task_id == NULL) + { + uos_sleep(10); + } + + while(1) + { + // receive message + mmi_voicechat_data_task_msg_t * msg = (mmi_voicechat_data_task_msg_t *)Hal_Receive_Message((TASK_ID)s_voicechat_data_recv_task_id, TRUE); + if(!msg) + continue; + + mm_voicechat_data_recv_task_handle(msg); + + Hal_Mem_Free(msg->cmd_param); + Hal_Mem_Free(msg); + } +} + +static void mmi_voicechat_data_recv_task_create(void) +{ + if(NULL != s_voicechat_data_recv_task_id) + return; + + s_voicechat_data_recv_task_id = uos_create_task(mm_voicechat_data_recv_task_entry, + NULL, + MMI_VOICECHAT_DATA_RECV_TASK_MSG_QUEUE_SIZE, + MMI_VOICECHAT_DATA_RECV_TASK_STACK_SIZE, + MMI_VOICECHAT_DATA_RECV_TASK_PRIORITY, + "mm_voicechat_data_recv_task"); + + printf("[@CHENG_DEBUG][%s][%d]: tcp_task_id=0x%x\n",__FUNCTION__,__LINE__, s_voicechat_data_recv_task_id); +} + +static void mmi_voicechat_data_recv_task_delete(void) +{ + if(NULL != s_voicechat_data_recv_task_id) + { + uos_delete_task(s_voicechat_data_recv_task_id); + s_voicechat_data_recv_task_id = NULL; + } +} +#endif + +// send task +static TASK_HANDLE * s_voicechat_data_send_task_id = NULL; + +static void mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_DATA_SEND_MSG_ID_E msg_id, void * param, uint32_t param_size) +{ + printf("[@CHENG_DEBUG][%s][%d]: msg_id=%d\n",__FUNCTION__,__LINE__, msg_id); + + if(NULL != s_voicechat_data_send_task_id) + { + if((MMI_VOICECHAT_DATA_SEND_TASK_MSG_QUEUE_SIZE - 1) < Hal_Get_Message_Count(s_voicechat_data_send_task_id)) + { + printf("[@CHENG_DEBUG][%s][%d]: msg queue full\n",__FUNCTION__,__LINE__); + return; + } + + printf("[@CHENG_DEBUG][%s][%d]: \n",__FUNCTION__,__LINE__); + + void * temp_ptr = NULL; + if(NULL != param && 0 != param_size) + { + temp_ptr = lv_mem_alloc(param_size + 1); + if(NULL == temp_ptr) + { + printf("[@CHENG_DEBUG][%s][%d]: memory alloc fail\n", __FUNCTION__, __LINE__); + return; + } + _lv_memset_00(temp_ptr, param_size + 1); + _lv_memcpy(temp_ptr, param, param_size); + } + + mmi_voicechat_data_task_msg_t * msg = Hal_Mem_Alloc(sizeof(mmi_voicechat_data_task_msg_t)); + msg->cmd_type = msg_id; + msg->cmd_param = temp_ptr; + msg->param_size = param_size; + + Hal_Send_Message((TASK_ID)s_voicechat_data_send_task_id, (void *)msg); + } +} + +static void mm_voicechat_data_send_task_handle(void * param) +{ + mmi_voicechat_data_task_msg_t * msg = (mmi_voicechat_data_task_msg_t *)param; + MMI_VOICECHAT_DATA_SEND_MSG_ID_E msg_id = msg->cmd_type; + void * msg_param = msg->cmd_param; + uint32_t param_size = msg->param_size; + + printf("[@CHENG_DEBUG][%s][%d]: msg_id=%d\n",__FUNCTION__,__LINE__, msg_id); + switch(msg_id) + { + case MMI_VOICECHAT_MSG_TRANS_START_SEND: + mmi_voicechat_send_trans_start_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_TRANS_AUDIO_SEND: + mmi_voicechat_send_trans_audio_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_TRANS_STOP_SEND: + //mmi_voicechat_send_trans_stop_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_CHAT_TEXT_SEND: + mmi_voicechat_send_chat_text_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_TTS_START_SEND: + //mmi_voicechat_send_tts_start_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_TTS_TEXT_SEND: + mmi_voicechat_send_tts_text_data_process(msg_param, param_size); + break; + + case MMI_VOICECHAT_MSG_TTS_STOP_SEND: + //mmi_voicechat_send_tts_stop_data_process(msg_param, param_size); + break; + + default: + break; + } +} + +static void mm_voicechat_data_send_task_entry(void * para) +{ + while(s_voicechat_data_send_task_id == NULL) + { + uos_sleep(10); + } + + while(1) + { + // receive message + mmi_voicechat_data_task_msg_t * msg = (mmi_voicechat_data_task_msg_t *)Hal_Receive_Message((TASK_ID)s_voicechat_data_send_task_id, TRUE); + if(!msg) + continue; + + mm_voicechat_data_send_task_handle(msg); + + Hal_Mem_Free(msg->cmd_param); + Hal_Mem_Free(msg); + } +} + +static void mmi_voicechat_data_send_task_create(void) +{ + if(NULL != s_voicechat_data_send_task_id) + return; + + s_voicechat_data_send_task_id = uos_create_task(mm_voicechat_data_send_task_entry, + NULL, + MMI_VOICECHAT_DATA_SEND_TASK_MSG_QUEUE_SIZE, + MMI_VOICECHAT_DATA_SEND_TASK_STACK_SIZE, + MMI_VOICECHAT_DATA_SEND_TASK_PRIORITY, + "mm_voicechat_data_send_task"); + + printf("[@CHENG_DEBUG][%s][%d]: tcp_task_id=0x%x\n",__FUNCTION__,__LINE__, s_voicechat_data_send_task_id); +} + +static void mmi_voicechat_data_send_task_delete(void) +{ + if(NULL != s_voicechat_data_send_task_id) + { + uos_delete_task(s_voicechat_data_send_task_id); + s_voicechat_data_send_task_id = NULL; + } +} + +void mmi_voicechat_data_task_create(void) +{ + //mmi_voicechat_data_recv_task_create(); + mmi_voicechat_data_send_task_create(); +} + +void mmi_voicechat_data_task_delete(void) +{ + //mmi_voicechat_data_recv_task_delete(); + mmi_voicechat_data_send_task_delete(); +} + + + +// trans +void mmi_voicechat_send_trans_start_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TRANS_START_SEND, NULL, 0); +} + +void mmi_voicechat_send_trans_audio_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TRANS_AUDIO_SEND, param, param_size); +} + +void mmi_voicechat_send_trans_stop_msg(void * param, uint32_t param_size) +{ + //mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TRANS_STOP_SEND, NULL, 0); +} + +static void mmi_voicechat_send_trans_start_data_process(void * data_ptr, uint32_t data_len) +{ + char send_ptr[512] = {0}; + int send_len = 0; + + send_len = sprintf(send_ptr, "{\"header\":{\"event\":\"StartTranscription\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"},\"payload\":{\"format\":\"amr\",\"sample_rate\":8000}}"); + + //int ret = mmi_voicechat_trans_websocket_send_text_data(send_ptr, send_len); + //if(0 > ret) + { + //VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + + //mmi_voicechat_trans_text_start_msg_send_fail(); + } +} + +static void mmi_voicechat_send_trans_audio_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d,data=%s\n", __FUNCTION__, __LINE__, data_len, data_ptr); + + //int ret = mmi_voicechat_trans_websocket_send_binary_data(data_ptr, data_len); + //if(0 > ret) + { + //VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + + //mmi_voicechat_trans_text_audio_msg_send_fail(); + } +} + +static void mmi_voicechat_send_trans_stop_data_process(void * data_ptr, uint32_t data_len) +{ +#if 0 + char send_ptr[512] = {0}; + int send_len = 0; + + send_len = sprintf(send_ptr, "{\"header\":{\"event\":\"StopTranscription\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"}}"); + + int ret = mmi_voicechat_trans_websocket_send_text_data(send_ptr, send_len); + if(0 > ret) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + } +#endif +} + +#if 0 +static void mmi_voicechat_trans_text_data_recv_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_recv_task_msg_send(MMI_VOICECHAT_MSG_TRANS_TEXT_RECV, param, param_size); +} + +static void mmi_voicechat_recv_trans_text_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: len=%d\n", __FUNCTION__, __LINE__, data_len); + cplog_printf("[@CHENG_DEBUG][%s][%d]: len=%d\n", __FUNCTION__, __LINE__, data_len); + if(NULL == data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); + return; + } + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_TRANS_FILE, data_ptr, data_len); +#endif + + cJSON * json_root = cJSON_Parse(data_ptr); + if(NULL != json_root) + { + cplog_printf("[@CHENG_DEBUG][%s][%d]: json root\n", __FUNCTION__, __LINE__); + + // "event" + char * value_event_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "event")); + if(0 == strncmp(value_event_str, "TranscriptionStarted", strlen("TranscriptionStarted"))) + { + // start + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: transcription start\n", __FUNCTION__, __LINE__); + + } + else if(0 == strncmp(value_event_str, "Changed", strlen("Changed"))) + { + // changed + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: changed\n", __FUNCTION__, __LINE__); + cJSON * json_result = cJSON_GetObjectItem(json_root, "result"); + if(NULL != json_result) + { + char * value_result_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_result, "result")); + uint32_t value_result_len = strlen(value_result_str); + + if(true == mmi_voicechat_trans_result_text_store(value_result_str, value_result_len, false)) + { + // refresh ui + mmi_voicechat_trans_text_middle_screen_update(); + } + } + } + else if(0 == strncmp(value_event_str, "SentenceEnd", strlen("SentenceEnd"))) + { + // end + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: transcription end\n", __FUNCTION__, __LINE__); + cJSON * json_result = cJSON_GetObjectItem(json_root, "result"); + if(NULL != json_result) + { + char * value_result_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_result, "result")); + uint32_t value_result_len = strlen(value_result_str); + + if(true == mmi_voicechat_trans_result_text_store(value_result_str, value_result_len, true)) + { + // refresh ui + mmi_voicechat_trans_text_stop_screen_update(); + } + } + } + else if(0 == strncmp(value_event_str, "TranscriptionCompleted", strlen("TranscriptionCompleted"))) + { + // stop + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: transcription stop\n", __FUNCTION__, __LINE__); + + } + } + +EXIT_AND_FREE: + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cplog_printf("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cJSON_Delete(json_root); + json_root = NULL; + } +} + + +void mmi_voicechat_trans_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + mmi_voicechat_trans_text_data_recv_msg(data_ptr, data_len); +} +#else + +void mmi_voicechat_trans_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + if(NULL == data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); + return; + } + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_TRANS_FILE, data_ptr, data_len); +#endif + + cJSON * json_root = cJSON_Parse(data_ptr); + if(NULL != json_root) + { + cplog_printf("[@CHENG_DEBUG][%s][%d]: json root\n", __FUNCTION__, __LINE__); + + // "event" + char * value_event_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "event")); + if(0 == strncmp(value_event_str, "TranscriptionStarted", strlen("TranscriptionStarted"))) + { + // start + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: transcription start\n", __FUNCTION__, __LINE__); + + } + else if(0 == strncmp(value_event_str, "Changed", strlen("Changed"))) + { + // changed + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: changed\n", __FUNCTION__, __LINE__); + cJSON * json_result = cJSON_GetObjectItem(json_root, "result"); + if(NULL != json_result) + { + char * value_result_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_result, "result")); + uint32_t value_result_len = strlen(value_result_str); + + if(true == mmi_voicechat_trans_result_text_store(value_result_str, value_result_len, false)) + { + // refresh ui + mmi_voicechat_trans_text_middle_screen_update(); + } + } + } + else if(0 == strncmp(value_event_str, "SentenceEnd", strlen("SentenceEnd"))) + { + // end + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: transcription end\n", __FUNCTION__, __LINE__); + cJSON * json_result = cJSON_GetObjectItem(json_root, "result"); + if(NULL != json_result) + { + char * value_result_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_result, "result")); + uint32_t value_result_len = strlen(value_result_str); + + if(true == mmi_voicechat_trans_result_text_store(value_result_str, value_result_len, true)) + { + // refresh ui + mmi_voicechat_trans_text_stop_screen_update(); + } + } + } + else if(0 == strncmp(value_event_str, "TranscriptionCompleted", strlen("TranscriptionCompleted"))) + { + // stop + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: transcription stop\n", __FUNCTION__, __LINE__); + + } + } + +EXIT_AND_FREE: + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cJSON_Delete(json_root); + json_root = NULL; + } +} +#endif + + + +// chat +void mmi_voicechat_send_chat_text_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_CHAT_TEXT_SEND, param, param_size); +} + +static void mmi_voicechat_send_chat_text_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d,data=%s\n", __FUNCTION__, __LINE__, data_len, data_ptr); + + uint32_t temp_len = 0; + uint32_t send_buff_len = data_len + 128; + char * send_buff_ptr = lv_mem_alloc(send_buff_len); + if(NULL == send_buff_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: memory alloc fail\n", __FUNCTION__, __LINE__); + return; + } + _lv_memset_00(send_buff_ptr, send_buff_len); + + temp_len = sprintf(send_buff_ptr, "{\"type\":\"chat\",\"content\":\"%s\"}", data_ptr); + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: send_len=%d\n", __FUNCTION__, __LINE__, temp_len); + //int ret = mmi_voicechat_chat_websocket_send_text_data(send_buff_ptr, temp_len); + //if(0 > ret) + { + //VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + } + + if(NULL != send_buff_ptr) + { + lv_mem_free(send_buff_ptr); + send_buff_ptr = NULL; + } +} + +#if 0 +static void mmi_voicechat_chat_text_data_recv_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_recv_task_msg_send(MMI_VOICECHAT_MSG_CHAT_TEXT_RECV, param, param_size); +} + +static void mmi_voicechat_recv_chat_text_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: len=%d\n", __FUNCTION__, __LINE__, data_len); + cplog_printf("[@CHENG_DEBUG][%s][%d]: len=%d\n", __FUNCTION__, __LINE__, data_len); + if(NULL == data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); + return; + } + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_CHAT_FILE, data_ptr, data_len); +#endif + + cJSON * json_root = cJSON_Parse(data_ptr); + if(NULL != json_root) + { + cplog_printf("[@CHENG_DEBUG][%s][%d]: json root\n", __FUNCTION__, __LINE__); + + // "type" + char * value_type_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "type")); + if(0 == strncmp(value_type_str, "start", strlen("start"))) + { + // start + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: chat start\n", __FUNCTION__, __LINE__); + + } + else if(0 == strncmp(value_type_str, "middle", strlen("middle"))) + { + // middle + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: chat middle\n", __FUNCTION__, __LINE__); + + char * value_content_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "content")); + uint32_t value_content_len = strlen(value_content_str); + + if(true == mmi_voicechat_chat_result_text_store(value_content_str, value_content_len)) + { + // send msg to refresh ui + //mmi_voicechat_chat_text_middle_screen_update(); + } + } + else if(0 == strncmp(value_type_str, "end", strlen("end"))) + { + // stop + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: chat stop\n", __FUNCTION__, __LINE__); + + // send msg to refresh ui + mmi_voicechat_chat_text_stop_screen_update(); + } + } + +EXIT_AND_FREE: + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cplog_printf("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cJSON_Delete(json_root); + json_root = NULL; + } +} + +void mmi_voicechat_chat_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + mmi_voicechat_chat_text_data_recv_msg(data_ptr, data_len); +} +#else + +void mmi_voicechat_chat_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + if(NULL == data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); + return; + } + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_CHAT_FILE, data_ptr, data_len); +#endif + + cJSON * json_root = cJSON_Parse(data_ptr); + if(NULL != json_root) + { + cplog_printf("[@CHENG_DEBUG][%s][%d]: json root\n", __FUNCTION__, __LINE__); + + // "type" + char * value_type_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "type")); + if(0 == strncmp(value_type_str, "start", strlen("start"))) + { + // start + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: chat start\n", __FUNCTION__, __LINE__); + + } + else if(0 == strncmp(value_type_str, "middle", strlen("middle"))) + { + // middle + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: chat middle\n", __FUNCTION__, __LINE__); + + char * value_content_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_root, "content")); + uint32_t value_content_len = strlen(value_content_str); + + if(true == mmi_voicechat_chat_result_text_store(value_content_str, value_content_len)) + { + // send msg to refresh ui + //mmi_voicechat_chat_text_middle_screen_update(); + } + } + else if(0 == strncmp(value_type_str, "end", strlen("end"))) + { + // stop + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: chat stop\n", __FUNCTION__, __LINE__); + + // send msg to refresh ui + mmi_voicechat_chat_text_stop_screen_update(); + } + } + +EXIT_AND_FREE: + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cJSON_Delete(json_root); + json_root = NULL; + } +} +#endif + + + +// tts +#if 0 +void mmi_voicechat_send_tts_start_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TTS_START_SEND, NULL, 0); +} + +void mmi_voicechat_send_tts_stop_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TTS_STOP_SEND, NULL, 0); +} + +void mmi_voicechat_send_tts_text_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TTS_TEXT_SEND, param, param_size); +} + +static void mmi_voicechat_send_tts_start_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d,data=%s\n", __FUNCTION__, __LINE__, data_len, data_ptr); + + char send_ptr[512] = {0}; + int send_len = 0; + + send_len = sprintf(send_ptr, "{\"header\":{\"event\":\"StartSynthesis\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"},\"payload\":{\"voice\":\"zhixiaomei\",\"format\":\"mp3\",\"sample_rate\":8000,\"volume\":50,\"speech_rate\":0}}"); + //send_len = sprintf(send_ptr, "{\"header\":{\"event\":\"StartSynthesis\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"},\"payload\":{\"voice\":\"xiaoyun\",\"format\":\"WAV\",\"sample_rate\":16000,\"volume\":50,\"speech_rate\":0}}"); + + int ret = mmi_voicechat_tts_websocket_send_text_data(send_ptr, send_len); + if(0 > ret) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + } +} + +static void mmi_voicechat_send_tts_stop_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d,data=%s\n", __FUNCTION__, __LINE__, data_len, data_ptr); + + char send_ptr[512] = {0}; + int send_len = 0; + + send_len = sprintf(send_ptr, "{\"header\":{\"event\":\"StopSynthesis\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"}}"); + + int ret = mmi_voicechat_tts_websocket_send_text_data(send_ptr, send_len); + if(0 > ret) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + } +} + +static void mmi_voicechat_send_tts_text_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: data=%s\n", __LINE__, data_ptr); + + uint32_t temp_len = 0; + uint32_t send_buff_len = data_len + 128; + char * send_buff_ptr = lv_mem_alloc(send_buff_len); + if(NULL == send_buff_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: memory alloc fail\n", __FUNCTION__, __LINE__); + return; + } + _lv_memset_00(send_buff_ptr, send_buff_len); + +#if 0 + temp_len = 0; + temp_len += sprintf(send_buff_ptr + temp_len, "{\"header\":{\"event\": \"LongTextStream\",\"trace_id\": \"3fa6b9e6a30b407ea38ad7ae69e6c291\"},"); + temp_len += sprintf(send_buff_ptr + temp_len, "\"payload\":{\"voice\":\"xiaoyun\",\"format\":\"amr\",\"sample_rate\":8000,\"volume\":50,\"speech_rate\":0,"); + temp_len += sprintf(send_buff_ptr + temp_len, "\"text\":\"%s\"}}", data_ptr); +#else + temp_len = 0; + temp_len += sprintf(send_buff_ptr + temp_len, "{\"header\":{\"event\":\"RunSynthesis\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"},"); + temp_len += sprintf(send_buff_ptr + temp_len, "\"payload\":{\"text\":\"%s\"}}", data_ptr); +#endif + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: send_len=%d\n", __FUNCTION__, __LINE__, temp_len); + int ret = mmi_voicechat_tts_websocket_send_text_data(send_buff_ptr, temp_len); + if(0 > ret) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + } + + if(NULL != send_buff_ptr) + { + lv_mem_free(send_buff_ptr); + send_buff_ptr = NULL; + } +} + +#else + +void mmi_voicechat_send_tts_text_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_send_task_msg_send(MMI_VOICECHAT_MSG_TTS_TEXT_SEND, param, param_size); +} + +static void mmi_voicechat_send_tts_text_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + uint32_t temp_len = 0; + uint32_t send_buff_len = data_len + 256; + char * send_buff_ptr = lv_mem_alloc(send_buff_len); + if(NULL == send_buff_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: memory alloc fail\n", __FUNCTION__, __LINE__); + return; + } + _lv_memset_00(send_buff_ptr, send_buff_len); + + temp_len = 0; + temp_len += sprintf(send_buff_ptr + temp_len, "{\"header\":{\"event\":\"LongTextStream\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"},"); + temp_len += sprintf(send_buff_ptr + temp_len, "\"payload\":{\"voice\":\"xiaoyun\",\"format\":\"mp3\",\"sample_rate\":8000,\"volume\":50,\"speech_rate\":2,"); // 0,"); + temp_len += sprintf(send_buff_ptr + temp_len, "\"text\":\"%s\"}}", data_ptr); // 185 + data_len + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_SEND_TTS_TEXT_FILE, send_buff_ptr, temp_len); +#endif + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: send_len=%d\n", __FUNCTION__, __LINE__, temp_len); + //int ret = mmi_voicechat_tts_websocket_send_text_data(send_buff_ptr, temp_len); + //if(0 > ret) + { + //VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: error=%d,send fail\n", __FUNCTION__, __LINE__, ret); + //mmi_voicechat_list_screen_signal_weak_prompt(); + } + + if(NULL != send_buff_ptr) + { + lv_mem_free(send_buff_ptr); + send_buff_ptr = NULL; + } +} + +#endif + +#if 0 +static void mmi_voicechat_tts_audio_data_recv_msg(void * param, uint32_t param_size) +{ + mmi_voicechat_data_recv_task_msg_send(MMI_VOICECHAT_MSG_TTS_AUDIO_RECV, param, param_size); +} + +static void mmi_voicechat_recv_tts_audio_data_process(void * data_ptr, uint32_t data_len) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: len=%d\n", __FUNCTION__, __LINE__, data_len); + cplog_printf("[@CHENG_DEBUG][%s][%d]: len=%d\n", __FUNCTION__, __LINE__, data_len); + if(NULL == data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); + return; + } + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_TTS_FILE, data_ptr, data_len); +#endif + + cJSON * json_root = cJSON_Parse(data_ptr); + if(NULL != json_root) + { + cplog_printf("[@CHENG_DEBUG][%s][%d]: json root\n", __FUNCTION__, __LINE__); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: tts json\n", __FUNCTION__, __LINE__); + + cJSON * json_header = cJSON_GetObjectItem(json_root, "header"); + if(NULL != json_header) + { + char * value_event_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_header, "event")); + if(0 == strncmp(value_event_str, "EndSynthesis", strlen("EndSynthesis"))) + { + // end + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: EndSynthesis\n", __FUNCTION__, __LINE__); + + mmi_voicechat_tts_end_synthesis_action(); + } + } + } + else + { + // tts data + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: tts data\n", __FUNCTION__, __LINE__); + + if(true == mmi_voicechat_tts_audio_store(data_ptr, data_len)) + { + + } + } + + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cplog_printf("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cJSON_Delete(json_root); + json_root = NULL; + } +} + +void mmi_voicechat_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + mmi_voicechat_tts_audio_data_recv_msg(data_ptr, data_len); +} +#else + +void mmi_voicechat_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: size=%d\n", __FUNCTION__, __LINE__, data_len); + + if(NULL == data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); + return; + } + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_TTS_FILE, data_ptr, data_len); +#endif + + cJSON * json_root = cJSON_Parse(data_ptr); + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: tts json\n", __FUNCTION__, __LINE__); + + cJSON * json_header = cJSON_GetObjectItem(json_root, "header"); + if(NULL != json_header) + { + char * value_event_str = cJSON_GetStringValue(cJSON_GetObjectItem(json_header, "event")); + if(0 == strncmp(value_event_str, "EndSynthesis", strlen("EndSynthesis"))) + { + // end + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: EndSynthesis\n", __FUNCTION__, __LINE__); + + mmi_voicechat_tts_end_synthesis_action(); + } + } + } + else + { + // tts data + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: tts data\n", __FUNCTION__, __LINE__); + + if(true == mmi_voicechat_tts_audio_store(data_ptr, data_len)) + { + + } + } + + if(NULL != json_root) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + //cplog_printf("[@CHENG_DEBUG][%s][%d]: free json root\n", __FUNCTION__, __LINE__); + cJSON_Delete(json_root); + json_root = NULL; + } +} +#endif + +#endif + diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_data.h b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_data.h new file mode 100644 index 00000000..fb4805b2 --- /dev/null +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_data.h @@ -0,0 +1,90 @@ + + + +#ifndef __MMI_VOICECHAT_DATA_H__ +#define __MMI_VOICECHAT_DATA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LV_CONF_INCLUDE_SIMPLE +#include "lvgl.h" +#include "lv_watch_conf.h" +#else +#include "../../../lvgl/lvgl.h" +#include "../../../lv_watch_conf.h" +#endif + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + +//#include "../../../../../product/craneg_modem/pcac/video_call/re/include/Re_hmac.h" +#include "hal/dm/cJSON.h" +#include "../../../../product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket.h" + + +#define MMI_VOICECHAT_DATA_SEND_TASK_PRIORITY 220 +#define MMI_VOICECHAT_DATA_SEND_TASK_MSG_QUEUE_SIZE (TASK_MSGQ_SIZE_16) +#define MMI_VOICECHAT_DATA_SEND_TASK_STACK_SIZE (16 * 1024) + +#define MMI_VOICECHAT_DATA_RECV_TASK_PRIORITY 220 +#define MMI_VOICECHAT_DATA_RECV_TASK_MSG_QUEUE_SIZE (TASK_MSGQ_SIZE_32) +#define MMI_VOICECHAT_DATA_RECV_TASK_STACK_SIZE (80 * 1024) + + + +typedef enum +{ + MMI_VOICECHAT_MSG_RECV_ID_START, + + MMI_VOICECHAT_MSG_TRANS_TEXT_RECV, + MMI_VOICECHAT_MSG_CHAT_TEXT_RECV, + MMI_VOICECHAT_MSG_TTS_AUDIO_RECV, + + MMI_VOICECHAT_MSG_RECV_ID_END +}MMI_VOICECHAT_DATA_RECV_MSG_ID_E; + +typedef enum +{ + MMI_VOICECHAT_MSG_SEND_ID_START, + + MMI_VOICECHAT_MSG_TRANS_START_SEND, + MMI_VOICECHAT_MSG_TRANS_AUDIO_SEND, + MMI_VOICECHAT_MSG_TRANS_STOP_SEND, + MMI_VOICECHAT_MSG_CHAT_TEXT_SEND, + MMI_VOICECHAT_MSG_TTS_START_SEND, + MMI_VOICECHAT_MSG_TTS_TEXT_SEND, + MMI_VOICECHAT_MSG_TTS_STOP_SEND, + + MMI_VOICECHAT_MSG_SEND_ID_END +}MMI_VOICECHAT_DATA_SEND_MSG_ID_E; + + + +typedef struct +{ + uint16_t cmd_type; + void * cmd_param; + uint32_t param_size; +}mmi_voicechat_data_task_msg_t; + + + +// data task +void mmi_voicechat_data_task_create(void); +void mmi_voicechat_data_task_delete(void); + +// trans +void mmi_voicechat_send_trans_start_msg(void * param, uint32_t param_size); +void mmi_voicechat_send_trans_audio_msg(void * param, uint32_t param_size); +void mmi_voicechat_send_trans_stop_msg(void * param, uint32_t param_size); +void mmi_voicechat_send_chat_text_msg(void * param, uint32_t param_size); + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_ui.c b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_ui.c new file mode 100644 index 00000000..756baf98 --- /dev/null +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_ui.c @@ -0,0 +1,2099 @@ + + + +#include "lv_watch.h" + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + +static lv_signal_cb_t ancient_scrl_signal; + +static MMI_VOICECHAT_UI_STATE_E s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_NONE; +static mmi_voicechat_msg_info_t s_voicechat_info_t = {0}; +static mmi_voicechat_msg_info_t * s_voicechat_info_p = &s_voicechat_info_t; +static uint8_t s_voicechat_current_chat_index = 0; // 1 chat = 2 msg items + +static uint32_t s_voicechat_recording_sent_size = 0; +static uint32_t s_voicechat_tts_text_sent_size = 0; +static bool s_voicechat_trans_text_end = false; +static bool s_voicechat_tts_audio_playing = false; + +static lv_ll_t s_voicechat_tts_audio_ll = {0}; +static mmi_voicechat_tts_audio_ll_t * s_voicechat_tts_audio_play_node = NULL; + +static bool s_voicechat_ws_open_flag = false; + +#define MMI_VOICECHAT_SEND_TTS_TEXT_MAX (150) // 50 +#define MMI_VOICECHAT_SEND_TTS_TEXT_MIN (99) // 33 + + +static lv_res_t mmi_voicechat_list_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param); +static void mmi_voicechat_list_set_slide_enable(lv_watch_obj_ext_t * ext, bool enable); +static void mmi_voicechat_default_screen_display(void); +static void mmi_voicechat_record_button_event_cb(lv_obj_t * obj, lv_event_t e); + + +#ifdef __MMI_ZHSX_SUPPORT__ +static bool s_is_ACT_ID_VOICECHAT_MAIN = false; + +bool mmi_is_ACT_ID_VOICECHAT_MAIN(void) +{ + return s_is_ACT_ID_VOICECHAT_MAIN; +} +#endif + +static void mmi_voicechat_trans_websocket_open(void) +{ + if(false == s_voicechat_ws_open_flag) + { + mmi_voicechat_websocket_app_start(); + s_voicechat_ws_open_flag = true; + } +} + +static void mmi_voicechat_chat_websocket_open(void) +{ + +} + +static void mmi_voicechat_tts_websocket_open(void) +{ + +} + +static void mmi_voicechat_trans_websocket_close(void) +{ + if(true == s_voicechat_ws_open_flag) + { + mmi_voicechat_websocket_app_stop(); + s_voicechat_ws_open_flag = false; + } +} + +static void mmi_voicechat_chat_websocket_close(void) +{ + +} + +static void mmi_voicechat_tts_websocket_close(void) +{ + +} + +static void mmi_voicechat_msg_data_clean(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + uint8_t i = 0; + for(i = 0; i < s_voicechat_info_p->msg_count; i++) + { + if(NULL != s_voicechat_info_p->msg_item[i].text_data_ptr) + { + lv_mem_free(s_voicechat_info_p->msg_item[i].text_data_ptr); + s_voicechat_info_p->msg_item[i].text_data_ptr = NULL; + } + + if(NULL != s_voicechat_info_p->msg_item[i].audio_data_ptr) + { + lv_mem_free(s_voicechat_info_p->msg_item[i].audio_data_ptr); + s_voicechat_info_p->msg_item[i].audio_data_ptr = NULL; + } + } + + _lv_memset_00(s_voicechat_info_p, sizeof(mmi_voicechat_msg_info_t)); +} + +uint8_t mmi_voicechat_msg_count_get(void) +{ + uint8_t msg_count = 0; + + msg_count = s_voicechat_info_p->msg_count; + + return msg_count; +} + +char * mmi_voicechat_trans_result_text_get(uint32_t * data_len) +{ + mmi_voicechat_msg_item_info_t * t_voicechat_item_info = &(s_voicechat_info_p->msg_item[0]); + + * data_len = t_voicechat_item_info->text_data_size; + return (t_voicechat_item_info->text_data_ptr); +} + +bool mmi_voicechat_trans_result_text_store(char * data_buff, uint32_t data_len, bool is_end) +{ + if(NULL == data_buff || 0 == data_len) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return false; + } + + if(true == s_voicechat_trans_text_end) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return false; + } + s_voicechat_trans_text_end = is_end; + + mmi_voicechat_msg_item_info_t * t_voicechat_item_info = &(s_voicechat_info_p->msg_item[0]); + +#if 1 + char * temp_ptr = lv_mem_alloc(data_len + 1); + if(NULL == temp_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: alloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr, data_len + 1); + _lv_memcpy(temp_ptr, data_buff, data_len); + + if(NULL != t_voicechat_item_info->text_data_ptr) + { + lv_mem_free(t_voicechat_item_info->text_data_ptr); + t_voicechat_item_info->text_data_ptr = NULL; + } + t_voicechat_item_info->text_data_ptr = temp_ptr; + t_voicechat_item_info->text_data_size = data_len; + +#else + if(NULL == t_voicechat_item_info->text_data_ptr) + { + char * temp_ptr = lv_mem_alloc(data_len + 1); + if(NULL == temp_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: alloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr, data_len + 1); + _lv_memcpy(temp_ptr, data_buff, data_len); + + t_voicechat_item_info->text_data_ptr = temp_ptr; + t_voicechat_item_info->text_data_size = data_len; + } + else + { + char * temp_ptr = lv_mem_realloc(t_voicechat_item_info->text_data_ptr, t_voicechat_item_info->text_data_size + data_len + 1); + if(NULL == temp_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: realloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr + t_voicechat_item_info->text_data_size, data_len + 1); + _lv_memcpy(temp_ptr + t_voicechat_item_info->text_data_size, data_buff, data_len); + + t_voicechat_item_info->text_data_ptr = temp_ptr; + t_voicechat_item_info->text_data_size += data_len; + } +#endif + t_voicechat_item_info->msg_from = 0; + s_voicechat_info_p->msg_count = 1; + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d,ptr=0x%x\n", __FUNCTION__, __LINE__, t_voicechat_item_info->text_data_size, t_voicechat_item_info->text_data_ptr); + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_TRANS_RESULT_FILE, t_voicechat_item_info->text_data_ptr, t_voicechat_item_info->text_data_size); +#endif + + return true; +} + +static void mmi_voicechat_trans_text_middle_screen_task_cb(lv_task_t * task) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: ui_state=%d\n", __FUNCTION__, __LINE__, s_voicechat_ui_state); + + if(MMI_VOICECHAT_UI_STATE_LISTENING == s_voicechat_ui_state || MMI_VOICECHAT_UI_STATE_LISTENING_MIDDLE == s_voicechat_ui_state) + { + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + mmi_voicechat_list_set_slide_enable(&ext->old_ext, true); + + if(0 != mmi_voicechat_msg_count_get()) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_listening_middle_screen_display(); + } + } +} + +void mmi_voicechat_trans_text_middle_screen_update(void) +{ + lv_task_t * task_p = lv_task_create(mmi_voicechat_trans_text_middle_screen_task_cb, 10, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +static void mmi_voicechat_trans_text_screen_close_task_cb(lv_task_t * task) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_thinking_screen_display(); + + mmi_voicechat_chat_text_download_requst(); +} + +static void mmi_voicechat_trans_text_stop_screen_task_cb(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: ui_state=%d\n", __FUNCTION__, __LINE__, s_voicechat_ui_state); + + // wb + mmi_voicechat_trans_websocket_close(); + mmi_voicechat_chat_websocket_open(); + + if(MMI_VOICECHAT_UI_STATE_LISTENING == s_voicechat_ui_state || MMI_VOICECHAT_UI_STATE_LISTENING_MIDDLE == s_voicechat_ui_state) + { + // record + mmi_voicechat_listening_stop(true); + + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + mmi_voicechat_list_set_slide_enable(&ext->old_ext, true); + + if(0 == mmi_voicechat_msg_count_get()) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_default_screen_display(); + } + else + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_listening_middle_screen_display(); + + lv_task_t * task_p = lv_task_create(mmi_voicechat_trans_text_screen_close_task_cb, 1000, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); + } + } +} + +void mmi_voicechat_trans_text_stop_screen_update(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_task_t * task_p = lv_task_create(mmi_voicechat_trans_text_stop_screen_task_cb, 10, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +static void mmi_voicechat_trans_text_fail_screen_task_cb(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_default_screen_display(); +} + +void mmi_voicechat_trans_text_start_msg_send_fail(void) +{ + mmi_voicechat_trans_websocket_close(); + mmi_voicechat_listening_stop(true); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + lv_obj_set_hidden(ext->listening_signal_weak_label, false); + + lv_task_t * task_p = lv_task_create(mmi_voicechat_trans_text_fail_screen_task_cb, 1500, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +void mmi_voicechat_trans_text_audio_msg_send_fail(void) +{ + mmi_voicechat_trans_websocket_close(); + mmi_voicechat_trans_websocket_open(); +} + + +char * mmi_voicechat_chat_result_text_get(uint32_t * data_len) +{ + mmi_voicechat_msg_item_info_t * t_voicechat_item_info = &(s_voicechat_info_p->msg_item[1]); + + * data_len = t_voicechat_item_info->text_data_size; + return (t_voicechat_item_info->text_data_ptr); +} + +bool mmi_voicechat_chat_result_text_store(char * data_buff, uint32_t data_len) +{ + if(NULL == data_buff || 0 == data_len) + { + printf("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return false; + } + + mmi_voicechat_msg_item_info_t * t_voicechat_item_info = &(s_voicechat_info_p->msg_item[1]); + + if(NULL == t_voicechat_item_info->text_data_ptr) + { + char * temp_ptr = lv_mem_alloc(data_len + 1); + if(NULL == temp_ptr) + { + printf("[@CHENG_DEBUG][%s][%d]: alloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr, data_len + 1); + _lv_memcpy(temp_ptr, data_buff, data_len); + + t_voicechat_item_info->text_data_ptr = temp_ptr; + t_voicechat_item_info->text_data_size = data_len; + } + else + { + char * temp_ptr = lv_mem_realloc(t_voicechat_item_info->text_data_ptr, t_voicechat_item_info->text_data_size + data_len + 1); + if(NULL == temp_ptr) + { + printf("[@CHENG_DEBUG][%s][%d]: realloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr + t_voicechat_item_info->text_data_size, data_len + 1); + _lv_memcpy(temp_ptr + t_voicechat_item_info->text_data_size, data_buff, data_len); + + t_voicechat_item_info->text_data_ptr = temp_ptr; + t_voicechat_item_info->text_data_size += data_len; + } + t_voicechat_item_info->msg_from = 1; + s_voicechat_info_p->msg_count = 2; + + printf("[@CHENG_DEBUG][%s][%d]: size=%d,ptr=0x%x\n", __FUNCTION__, __LINE__, t_voicechat_item_info->text_data_size, t_voicechat_item_info->text_data_ptr); + +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE + mmi_debug_info_write_to_file(VOICECHAT_RECV_CHAT_RESULT_FILE, t_voicechat_item_info->text_data_ptr, t_voicechat_item_info->text_data_size); +#endif + + return true; +} + +void mmi_voicechat_chat_text_middle_task_cb(lv_task_t * task) +{ + if(MMI_VOICECHAT_UI_STATE_THINKING == s_voicechat_ui_state) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + if(NULL != ext->thinking_task_p) + { + lv_task_del(ext->thinking_task_p); + ext->thinking_task_p = NULL; + } + + mmi_voicechat_list_screen_display(); + } + else if(MMI_VOICECHAT_UI_STATE_LIST == s_voicechat_ui_state) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + mmi_voicechat_msg_item_info_t * msg_item = &(s_voicechat_info_p->msg_item[1]); + char * file_buf = msg_item->text_data_ptr; + + lv_label_set_text(ext->list_other_label, file_buf); + } +} + +void mmi_voicechat_chat_text_middle_screen_update(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_task_t * task_p = lv_task_create(mmi_voicechat_chat_text_middle_task_cb, 10, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +static void mmi_voicechat_chat_text_stop_screen_task_cb(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: ui_state=%d\n", __FUNCTION__, __LINE__, s_voicechat_ui_state); + + // wb + mmi_voicechat_chat_websocket_close(); + mmi_voicechat_tts_websocket_open(); + + if((MMI_VOICECHAT_UI_STATE_THINKING == s_voicechat_ui_state) || (MMI_VOICECHAT_UI_STATE_LIST == s_voicechat_ui_state)) + { + mmi_voicechat_main_screen_refresh(); + + mmi_voicechat_tts_audio_download_requst(); + } +} + +void mmi_voicechat_chat_text_stop_screen_update(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_task_t * task_p = lv_task_create(mmi_voicechat_chat_text_stop_screen_task_cb, 10, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +void mmi_voicechat_chat_text_download_requst(void) +{ + uint32_t data_len = 0; + char * data_ptr = mmi_voicechat_trans_result_text_get(&data_len); + + if(NULL != data_ptr && 0 != data_len) + { + mmi_voicechat_send_chat_text_msg(data_ptr, data_len); + } +} + + +static void mmi_utf8_complete_character_judge(char * data_ptr, uint32_t data_len, uint32_t * output_len) +{ + uint32_t i = 0; + uint32_t p = 0; + char ch = 0; + while(1) + { + ch = data_ptr[i]; + + //#1111110x + if(ch >= 252) + p = p + 6; + //#111110xx + else if(ch >= 248) + p = p + 5; + //#11110xxx + else if(ch >= 240) + p = p + 4; + //#1110xxxx + else if(ch >= 224) + p = p + 3; + //#110xxxxx + else if(ch >= 192) + p = p + 2; + else + p = p + 1; + + if(p >= data_len) + break; + else + i = p; + } + + * output_len = i; + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: output_len=%d\n", __FUNCTION__, __LINE__, *output_len); +} + +void mmi_voicechat_send_tts_text_seperate(char * data_ptr, uint32_t data_len, uint32_t * output_len) +{ + // cn , + char cn_comma_str[4] = {0}; + cn_comma_str[0] = 0XEF; + cn_comma_str[1] = 0XBC; + cn_comma_str[2] = 0X8C; + + // cn . + char cn_period_str[4] = {0}; + cn_period_str[0] = 0XE3; + cn_period_str[1] = 0X80; + cn_period_str[2] = 0X82; + + // cn ? + char cn_query_str[4] = {0}; + cn_query_str[0] = 0XEF; + cn_query_str[1] = 0XBC; + cn_query_str[2] = 0X9F; + + // cn ! + char cn_mark_str[4] = {0}; + cn_mark_str[0] = 0XEF; + cn_mark_str[1] = 0XBC; + cn_mark_str[2] = 0X81; + + + if(MMI_VOICECHAT_SEND_TTS_TEXT_MAX >= data_len) + { + * output_len = data_len; + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: output_len=%d\n", __FUNCTION__, __LINE__, *output_len); + return; + } + + char * temp_ptr = lv_mem_alloc(MMI_VOICECHAT_SEND_TTS_TEXT_MAX + 1); + if(NULL == temp_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: alloc memory fail\n", __FUNCTION__, __LINE__); + return ; + } + _lv_memset_00(temp_ptr, (MMI_VOICECHAT_SEND_TTS_TEXT_MAX + 1)); + _lv_memcpy(temp_ptr, data_ptr, MMI_VOICECHAT_SEND_TTS_TEXT_MAX); + + char * offset_ptr = NULL; + offset_ptr = strstr(temp_ptr, cn_comma_str); + if(NULL != offset_ptr) + { + * output_len = offset_ptr - temp_ptr + 2; + goto EXIT; + } + + offset_ptr = strstr(temp_ptr, cn_period_str); + if(NULL != offset_ptr) + { + * output_len = offset_ptr - temp_ptr + 2; + goto EXIT; + } + + offset_ptr = strstr(temp_ptr, cn_query_str); + if(NULL != offset_ptr) + { + * output_len = offset_ptr - temp_ptr + 2; + goto EXIT; + } + + offset_ptr = strstr(temp_ptr, cn_mark_str); + if(NULL != offset_ptr) + { + * output_len = offset_ptr - temp_ptr + 2; + goto EXIT; + } + + if(NULL == offset_ptr) + { + mmi_utf8_complete_character_judge(temp_ptr, MMI_VOICECHAT_SEND_TTS_TEXT_MIN, output_len); + } + +EXIT: + lv_mem_free(temp_ptr); + temp_ptr = NULL; + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: output_len=%d\n", __FUNCTION__, __LINE__, *output_len); +} + +uint32_t mmi_voicechat_send_tts_text_data_escape_character(char * data_buff, int data_len, char * output_data) +{ + if (NULL == data_buff || 0 == data_len) + return; + + uint32_t curr_p = 0, i = 0; + + for(i = 0; i < data_len; i++) + { + if(0X0A == data_buff[i]) // 0X0A -> 0X5C 0X6E + { + output_data[curr_p++] = 0X5C; + output_data[curr_p++] = 0X6E; + } + else if(0X22 == data_buff[i]) // 0X22 -> 0X5C 0X22 + { + output_data[curr_p++] = 0X5C; + output_data[curr_p++] = 0X22; + } + else + { + output_data[curr_p++] = data_buff[i]; + } + } + + return curr_p; +} + +void mmi_voicechat_send_tts_text_action(char * data_ptr, uint32_t data_len) +{ + uint32_t output_len = 0; + mmi_voicechat_send_tts_text_seperate(data_ptr, data_len, &output_len); + + uint32_t send_len = 0; + char * send_ptr = lv_mem_alloc((output_len + output_len / 9 + 1)); + if(NULL == send_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: alloc memory fail\n", __FUNCTION__, __LINE__); + return ; + } + _lv_memset_00(send_ptr, (output_len + output_len / 9 + 1)); + send_len = mmi_voicechat_send_tts_text_data_escape_character(data_ptr, output_len, send_ptr); + +#if 0 + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: send_len=%d\n", __FUNCTION__, __LINE__, send_len); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[0],send_ptr[1],send_ptr[2],send_ptr[3],send_ptr[4],send_ptr[5],send_ptr[6],send_ptr[7],send_ptr[8],send_ptr[9]); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[10],send_ptr[11],send_ptr[12],send_ptr[13],send_ptr[14],send_ptr[15],send_ptr[16],send_ptr[17],send_ptr[18],send_ptr[19]); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[20],send_ptr[21],send_ptr[22],send_ptr[23],send_ptr[24],send_ptr[25],send_ptr[26],send_ptr[27],send_ptr[28],send_ptr[29]); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[30],send_ptr[31],send_ptr[32],send_ptr[33],send_ptr[34],send_ptr[35],send_ptr[36],send_ptr[37],send_ptr[38],send_ptr[39]); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[40],send_ptr[41],send_ptr[42],send_ptr[43],send_ptr[44],send_ptr[45],send_ptr[46],send_ptr[47],send_ptr[48],send_ptr[49]); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[50],send_ptr[51],send_ptr[52],send_ptr[53],send_ptr[54],send_ptr[55],send_ptr[56],send_ptr[57],send_ptr[58],send_ptr[59]); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: %#X %#X %#X %#X %#X %#X %#X %#X %#X %#X\n", __LINE__, + send_ptr[60],send_ptr[61],send_ptr[62],send_ptr[63],send_ptr[64],send_ptr[65],send_ptr[66],send_ptr[67],send_ptr[68],send_ptr[69]); +#endif + + mmi_voicechat_send_tts_text_msg(send_ptr, send_len); + s_voicechat_tts_text_sent_size += output_len; + + lv_mem_free(send_ptr); + send_ptr = NULL; +} + +void mmi_voicechat_send_tts_text_action_pre(void) +{ + uint32_t node_total = mmi_voicechat_tts_audio_ll_node_num(); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: node_total=%d\n", __FUNCTION__, __LINE__, node_total); + + uint32_t data_len = 0; + char * data_ptr = mmi_voicechat_chat_result_text_get(&data_len); + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: data_len=%d,sent_len=%d\n", __FUNCTION__, __LINE__, data_len, s_voicechat_tts_text_sent_size); + if((NULL != data_ptr) && (data_len > s_voicechat_tts_text_sent_size)) + { + //mmi_voicechat_tts_audio_ll_new_tail_node(); + + mmi_voicechat_send_tts_text_action(data_ptr + s_voicechat_tts_text_sent_size, data_len - s_voicechat_tts_text_sent_size); + } +} + +void mmi_voicechat_tts_audio_download_requst(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + s_voicechat_tts_text_sent_size = 0; + s_voicechat_tts_audio_playing = false; + mmi_voicechat_tts_audio_ll_clean(); + mmi_voicechat_tts_audio_ll_new_tail_node(); + mmi_voicechat_send_tts_text_action_pre(); +} + + +void mmi_voicechat_tts_audio_ll_init(void) +{ + _lv_ll_init(&s_voicechat_tts_audio_ll, sizeof(mmi_voicechat_tts_audio_ll_t)); + _lv_ll_clear(&s_voicechat_tts_audio_ll); +} + +void mmi_voicechat_tts_audio_ll_clean(void) +{ + mmi_voicechat_tts_audio_ll_t * node = NULL; + for(node = _lv_ll_get_head(&s_voicechat_tts_audio_ll); NULL != node; node = _lv_ll_get_next((&s_voicechat_tts_audio_ll), node)) + { + if(NULL != node->audio_data_ptr) + { + lv_mem_free(node->audio_data_ptr); + node->audio_data_ptr = NULL; + } + } + + _lv_ll_clear(&s_voicechat_tts_audio_ll); +} + +uint32_t mmi_voicechat_tts_audio_ll_node_num(void) +{ + uint32_t node_total = _lv_ll_get_len(&s_voicechat_tts_audio_ll); + + //VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: node_total=%d\n", __FUNCTION__, __LINE__, node_total); + return node_total; +} + +mmi_voicechat_tts_audio_ll_t * mmi_voicechat_tts_audio_ll_new_tail_node(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_tts_audio_ll_t * node = _lv_ll_ins_tail(&s_voicechat_tts_audio_ll); + + node->audio_data_ptr = NULL; + node->audio_data_size = 0; + + return node; +} + +bool mmi_voicechat_tts_audio_store(char * data_buff, uint32_t data_len) +{ + if(NULL == data_buff || 0 == data_len) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return false; + } + + mmi_voicechat_tts_audio_ll_t * node = _lv_ll_get_tail(&s_voicechat_tts_audio_ll); + if(NULL == node) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return false; + } + + if(NULL == node->audio_data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + char * temp_ptr = lv_mem_alloc(data_len + 1); + if(NULL == temp_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: alloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr, data_len + 1); + _lv_memcpy(temp_ptr, data_buff, data_len); + + node->audio_data_ptr = temp_ptr; + node->audio_data_size = data_len; + } + else + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + char * temp_ptr = lv_mem_realloc(node->audio_data_ptr, node->audio_data_size + data_len + 1); + if(NULL == temp_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: realloc memory fail\n", __FUNCTION__, __LINE__); + return false; + } + _lv_memset_00(temp_ptr + node->audio_data_size, data_len + 1); + _lv_memcpy(temp_ptr + node->audio_data_size, data_buff, data_len); + + node->audio_data_ptr = temp_ptr; + node->audio_data_size += data_len; + } + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d,ptr=0x%x\n", __FUNCTION__, __LINE__, node->audio_data_size, node->audio_data_ptr); + + return true; +} + +void mmi_voicechat_tts_audio_ctrl_callback(AUDIO_CTRL_PRIORITY priority) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: priority=%d\n", __FUNCTION__, __LINE__, priority); + + if(MMI_VOICECHAT_TTS_AUDIO_PRI == priority) + { + + } + else if(MMI_VOICECHAT_TTS_AUDIO_PRI > priority) + { + // wb + mmi_voicechat_tts_websocket_close(); + + // res + mmi_voicechat_tts_audio_ll_clean(); + + Hal_NFFS_File_Play_End(); + Hal_Audio_Manage_End_Ind(MMI_VOICECHAT_TTS_AUDIO_PRI); + } +} + +static void mmi_voicechat_tts_audio_over_cb(void * para) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + s_voicechat_tts_audio_playing = false; + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: node=%#X,total=%d\n", __FUNCTION__, __LINE__, s_voicechat_tts_audio_play_node, mmi_voicechat_tts_audio_ll_node_num()); + mmi_voicechat_tts_audio_ll_t * node = _lv_ll_get_next((&s_voicechat_tts_audio_ll), s_voicechat_tts_audio_play_node); + _lv_ll_remove((&s_voicechat_tts_audio_ll), s_voicechat_tts_audio_play_node); + if(NULL != s_voicechat_tts_audio_play_node->audio_data_ptr) + { + lv_mem_free(s_voicechat_tts_audio_play_node->audio_data_ptr); + s_voicechat_tts_audio_play_node->audio_data_ptr = NULL; + } + lv_mem_free(s_voicechat_tts_audio_play_node); + s_voicechat_tts_audio_play_node = NULL; + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: node=%#X,total=%d\n", __FUNCTION__, __LINE__, node, mmi_voicechat_tts_audio_ll_node_num()); + + // get tts + //mmi_voicechat_send_tts_text_action_pre(); + + if(MMI_VOICECHAT_TTS_AUDIO_PRI == Hal_Audio_Manage_Start_Req(MMI_VOICECHAT_TTS_AUDIO_PRI, mmi_voicechat_tts_audio_ctrl_callback)) + { + if(NULL == node || NULL == node->audio_data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return ; + } + s_voicechat_tts_audio_play_node = node; + s_voicechat_tts_audio_playing = true; + + Hal_Tone_Play_Onetime((uint32_t *)node->audio_data_ptr, + node->audio_data_size, + HAL_AUDIO_SPK_LEVEL_MAX, + mmi_voicechat_tts_audio_over_cb, + NULL); + } +} + +bool mmi_voicechat_tts_audio_play(void) +{ + if(true == s_voicechat_tts_audio_playing) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return false; + } + + if(MMI_VOICECHAT_TTS_AUDIO_PRI == Hal_Audio_Manage_Start_Req(MMI_VOICECHAT_TTS_AUDIO_PRI, mmi_voicechat_tts_audio_ctrl_callback)) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_tts_audio_ll_t * node = _lv_ll_get_head(&s_voicechat_tts_audio_ll); + if(NULL == node) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: tt audio ll empty\n", __FUNCTION__, __LINE__); + return false; + } + else + { + if(NULL == node->audio_data_ptr) + { + node = _lv_ll_get_next((&s_voicechat_tts_audio_ll), node); + if(NULL == node || NULL == node->audio_data_ptr) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: no data\n", __FUNCTION__, __LINE__); +#if 0 +{ + uint32_t node_total = mmi_voicechat_tts_audio_ll_node_num(); + uint8_t i = 0; + mmi_voicechat_tts_audio_ll_t * node = _lv_ll_get_head(&s_voicechat_tts_audio_ll); + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: node_total=%d\n", __FUNCTION__, __LINE__, node_total); + for(i = 0; i < node_total; i++) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: %d,%#X,%#X\n", __FUNCTION__, __LINE__, i, node, node->audio_data_ptr); + + node = _lv_ll_get_next((&s_voicechat_tts_audio_ll), node); + } +} +#endif + return false; + } + } + } + s_voicechat_tts_audio_play_node = node; + s_voicechat_tts_audio_playing = true; + + Hal_Tone_Play_Onetime((uint32_t *)node->audio_data_ptr, + node->audio_data_size, + HAL_AUDIO_SPK_LEVEL_MAX, + mmi_voicechat_tts_audio_over_cb, + NULL); + } + + return true; +} + +void mmi_voicechat_tts_end_synthesis_action(void) +{ + mmi_voicechat_tts_audio_ll_new_tail_node(); + mmi_voicechat_send_tts_text_action_pre(); + + // + mmi_voicechat_tts_audio_play(); +} + + +void mmi_voicechat_list_screen_prompt_clean_task_cb(lv_task_t * task) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + lv_obj_set_hidden(ext->list_signal_weak_label, true); +} + +void mmi_voicechat_list_screen_prompt_task_cb(lv_task_t * task) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + lv_obj_set_hidden(ext->list_signal_weak_label, false); + + lv_task_t * task_p = lv_task_create(mmi_voicechat_list_screen_prompt_clean_task_cb, 1500, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +void mmi_voicechat_list_screen_signal_weak_prompt(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + if(MMI_VOICECHAT_UI_STATE_LIST != s_voicechat_ui_state) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return; + } + + lv_task_t * task_p = lv_task_create(mmi_voicechat_list_screen_prompt_task_cb, 10, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(task_p); +} + +void * mmi_voicechat_actId_ext_get(lv_watch_Activity_Id_t actId) +{ + lv_obj_t * activity_obj = lv_watch_get_activity_obj(actId); + if(NULL == activity_obj) + return NULL; + + lv_obj_t * watch_obj = NULL; + lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj); + if(NULL != watch_obj) + { + void * ext = lv_obj_get_ext_attr(watch_obj); + return ext; + } + + return NULL; +} + +static void mmi_voicechat_lv_style_reset(void) +{ + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + lv_style_reset(&(ext->style_cont_self)); + lv_style_reset(&(ext->style_cont_other)); + //lv_style_reset(&(ext->style_label_time)); + lv_style_reset(&(ext->style_label_len_self)); + lv_style_reset(&(ext->style_label_len_other)); +} + +static void mmi_voicechat_lv_style_set(void) +{ + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + //lv_style_init(&(ext->style_label_time)); + //lv_style_copy(&(ext->style_label_time), &lv_watch_font20); + //lv_style_set_text_color(&(ext->style_label_time), LV_STATE_DEFAULT, lv_color_make(20, 187, 242)); + + lv_style_init(&(ext->style_label_len_other)); + lv_style_copy(&(ext->style_label_len_other), &lv_watch_font20); + lv_style_set_text_color(&(ext->style_label_len_other), LV_STATE_DEFAULT, LV_COLOR_WHITE); + + lv_style_init(&(ext->style_label_len_self)); + lv_style_copy(&(ext->style_label_len_self), &lv_watch_font20); + lv_style_set_text_color(&(ext->style_label_len_self), LV_STATE_DEFAULT, LV_COLOR_WHITE); + + lv_style_init(&(ext->style_cont_self)); + lv_style_set_bg_color(&(ext->style_cont_self), LV_STATE_DEFAULT, LV_COLOR_MAKE(79, 195, 76)); // LV_COLOR_MAKE(175, 242, 89)); + lv_style_set_radius(&(ext->style_cont_self), LV_STATE_DEFAULT, 15); // 30 + lv_style_set_pad_top(&(ext->style_cont_self), LV_STATE_DEFAULT, 10); // 8 + lv_style_set_pad_bottom(&(ext->style_cont_self), LV_STATE_DEFAULT, 10); // 8 + lv_style_set_pad_left(&(ext->style_cont_self), LV_STATE_DEFAULT, 5); // 8 + lv_style_set_pad_right(&(ext->style_cont_self), LV_STATE_DEFAULT, 5); // 8 + + lv_style_init(&(ext->style_cont_other)); + lv_style_set_bg_color(&(ext->style_cont_other), LV_STATE_DEFAULT, LV_COLOR_MAKE(25, 25, 25)); // LV_COLOR_MAKE(0xE2, 0xBD, 0xFF)); + lv_style_set_radius(&(ext->style_cont_other), LV_STATE_DEFAULT, 15); + lv_style_set_pad_top(&(ext->style_cont_other), LV_STATE_DEFAULT, 10); + lv_style_set_pad_bottom(&(ext->style_cont_other), LV_STATE_DEFAULT, 10); + lv_style_set_pad_left(&(ext->style_cont_other), LV_STATE_DEFAULT, 5); + lv_style_set_pad_right(&(ext->style_cont_other), LV_STATE_DEFAULT, 5); +} + +void mmi_voicechat_main_prepare_destory(lv_obj_t * activity_obj) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + // websocket + mmi_voicechat_trans_websocket_close(); + mmi_voicechat_chat_websocket_close(); + mmi_voicechat_tts_websocket_close(); + + // data task + mmi_voicechat_data_task_delete(); + watch_set_suspend_enable(true, ACT_ID_VOICECHAT_MAIN, 0); + + // free resource + mmi_voicechat_msg_data_clean(); + mmi_voicechat_tts_audio_ll_clean(); + + // audio + mmi_voicechat_listening_stop(true); + Hal_NFFS_File_Play_End(); + Hal_Audio_Manage_End_Ind(MMI_VOICECHAT_TTS_AUDIO_PRI); + //Hal_Vibrator_Play_End(); + + lv_watch_png_cache_all_free(); + mmi_voicechat_lv_style_reset(); + + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + if(NULL != ext->record_buffer) + { + lv_mem_free(ext->record_buffer); + ext->record_buffer = NULL; + } + + if(NULL != ext->thinking_task_p) + { + lv_task_del(ext->thinking_task_p); + ext->thinking_task_p = NULL; + } + if(NULL != ext->gif_listening) + { + gif_close(ext->gif_listening); + ext->gif_listening = NULL; + } + if(NULL != ext->gif_thinking) + { + gif_close(ext->gif_thinking); + ext->gif_thinking = NULL; + } + +#ifdef __MMI_ZHSX_SUPPORT__ + s_is_ACT_ID_VOICECHAT_MAIN = false; +#endif +} + +void mmi_voicechat_main_screen_clean(void) +{ + mmi_voicechat_main_prepare_destory(NULL); + + lv_obj_t * obj = lv_watch_get_activity_obj(ACT_ID_VOICECHAT_MAIN); + if(NULL != obj) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + lv_obj_del(obj); + } +} + +static void mmi_voicechat_list_set_slide_enable(lv_watch_obj_ext_t * ext, bool enable) +{ + if(enable) + { + ext->slide_enable = 1; /*enable to slide to the right*/ + } + else + { + ext->slide_enable = 0; /*disable to slide to the right*/ + } +} + +void mmi_voicechat_timeout_screen_clean(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_default_screen_display(); +} + +void mmi_voicechat_timeout_screen_display(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_CONNECT_TIMEOUT; + + if(NULL != ext->thinking_task_p) + { + lv_task_del(ext->thinking_task_p); + ext->thinking_task_p = NULL; + } + + + // ui + lv_obj_t * cont = ext->cont_timeout; + + //label + lv_obj_t * label_state = lv_label_create(cont, NULL); + lv_obj_add_style(label_state, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label_state, WATCH_TEXT_ID_VOICECHAT); + lv_label_set_align(label_state, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label_state, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + lv_obj_t * img = lv_img_create(cont, NULL); + lv_img_set_src(img, ICON_VOICECHAT_PROMPT); + lv_obj_set_click(img, false); + lv_obj_align(img, NULL, LV_ALIGN_IN_TOP_MID, 0, 70); + + lv_obj_t * label = lv_label_create(cont, NULL); + lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label, WATCH_TEXT_ID_AIGC_CONNECT_TIMEOUT); + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, img, LV_ALIGN_OUT_BOTTOM_MID, 0, 25); + + lv_obj_t * imgbtn = lv_imgbtn_create(cont, NULL); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_RELEASED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_PRESSED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_obj_set_event_cb(imgbtn, mmi_voicechat_record_button_event_cb); + lv_obj_add_protect(imgbtn, LV_PROTECT_PRESS_LOST); + lv_watch_obj_add_element(imgbtn); + lv_obj_align(imgbtn, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -20); + + lv_obj_t * imgbtn_label = lv_label_create(imgbtn, NULL); + lv_obj_add_style(imgbtn_label, LV_LABEL_PART_MAIN, &lv_watch_font26); + lv_label_set_align(imgbtn_label, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_id(imgbtn_label, WATCH_TEXT_ID_OK); + lv_obj_align(imgbtn_label, NULL, LV_ALIGN_CENTER, 0, 0); + + lv_obj_set_hidden(ext->cont_default, true); + lv_obj_set_hidden(ext->cont_listening, true); + lv_obj_set_hidden(ext->cont_listening_middle, true); + lv_obj_set_hidden(ext->cont_thinking, true); + lv_obj_set_hidden(ext->cont_timeout, false); + lv_obj_set_hidden(ext->cont_list, true); +} + +void mmi_voicechat_thinking_screen_clean(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_chat_websocket_close(); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + if(NULL != ext->thinking_task_p) + { + lv_task_del(ext->thinking_task_p); + ext->thinking_task_p = NULL; + } + + mmi_voicechat_default_screen_display(); +} + +static void mmi_voicechat_thinking_screen_task_cb(lv_task_t * task) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_timeout_screen_display(); +} + +void mmi_voicechat_listening_remain_data_send(void) +{ +#if 0 + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + goto EXIT; + } + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: size=%d, buf=0x%x\n", __FUNCTION__, __LINE__, ext->record_size, ext->record_buffer); + + int file_size = ext->record_size - s_voicechat_recording_sent_size; + if(0 >= file_size) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + goto EXIT; + } + char * file_buf = lv_mem_alloc(file_size + 1); + if(NULL == file_buf) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + goto EXIT; + } + _lv_memset_00(file_buf, file_size + 1); + _lv_memcpy(file_buf, ext->record_buffer + s_voicechat_recording_sent_size, file_size); + + mmi_voicechat_send_trans_audio_msg(file_buf, file_size); + lv_mem_free(file_buf); + file_buf = NULL; + +EXIT: + lv_mem_free(ext->record_buffer); + ext->record_buffer = NULL; + ext->record_size = 0; + + s_voicechat_recording_sent_size = 0; +#endif +} + +void mmi_voicechat_thinking_screen_display(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_THINKING; + + //mmi_voicechat_listening_remain_data_send(); + + if(NULL != ext->thinking_task_p) + { + lv_task_del(ext->thinking_task_p); + ext->thinking_task_p = NULL; + } + ext->thinking_task_p = lv_task_create(mmi_voicechat_thinking_screen_task_cb, 60 * 1000, LV_TASK_PRIO_HIGH, NULL); + lv_task_once(ext->thinking_task_p); + + + // ui + lv_obj_t * cont = ext->cont_thinking; + if(NULL != ext->gif_thinking) + { + gif_close(ext->gif_thinking); + ext->gif_thinking = NULL; + } + lv_obj_clean(cont); + + //label + lv_obj_t * label_state = lv_label_create(cont, NULL); + lv_obj_add_style(label_state, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label_state, WATCH_TEXT_ID_AIGC_THINKING); + lv_label_set_align(label_state, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label_state, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + ext->gif_thinking = gif_open(cont, ANIM_VOICECHAT_THINKING, 0); + if(NULL == ext->gif_thinking) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: gif open fail\n", __FUNCTION__, __LINE__); + } + lv_obj_set_style_local_bg_color(ext->gif_thinking->container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_align(ext->gif_thinking->container, NULL, LV_ALIGN_CENTER, 0, -10); + + lv_obj_t * imgbtn = lv_imgbtn_create(cont, NULL); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_RELEASED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_PRESSED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_obj_set_event_cb(imgbtn, mmi_voicechat_record_button_event_cb); + lv_obj_add_protect(imgbtn, LV_PROTECT_PRESS_LOST); + lv_watch_obj_add_element(imgbtn); + lv_obj_align(imgbtn, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -20); + + lv_obj_t * imgbtn_label = lv_label_create(imgbtn, NULL); + lv_obj_add_style(imgbtn_label, LV_LABEL_PART_MAIN, &lv_watch_font26); + //lv_obj_set_style_local_text_font(imgbtn_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_THEME_WATCH_NIGHT_FONT_26); + //lv_obj_set_style_local_text_color(imgbtn_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(253, 82, 19)); + lv_label_set_align(imgbtn_label, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_id(imgbtn_label, WATCH_TEXT_ID_CANCEL); + lv_obj_align(imgbtn_label, NULL, LV_ALIGN_CENTER, 0, 0); + + lv_obj_set_hidden(ext->cont_default, true); + lv_obj_set_hidden(ext->cont_listening, true); + lv_obj_set_hidden(ext->cont_listening_middle, true); + lv_obj_set_hidden(ext->cont_thinking, false); + lv_obj_set_hidden(ext->cont_timeout, true); + lv_obj_set_hidden(ext->cont_list, true); +} + +void mmi_voicechat_listening_middle_screen_display(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_LISTENING_MIDDLE; + + // ui + lv_obj_t * cont = ext->cont_listening_middle; + if(NULL != ext->gif_listening) + { + gif_close(ext->gif_listening); + ext->gif_listening = NULL; + } + lv_obj_clean(cont); + + + lv_obj_t * list_page = lv_page_create(cont, NULL); + lv_obj_set_size(list_page, lv_obj_get_width(cont), lv_obj_get_height(cont) / 2); + lv_page_set_scrollbar_mode(list_page, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_local_bg_opa(list_page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_border_opa(list_page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_outline_width(list_page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, 0); + lv_obj_align(list_page, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + lv_page_set_scrl_layout(list_page, LV_LAYOUT_OFF); + lv_page_set_scrollable_fit2(list_page, LV_FIT_NONE, LV_FIT_TIGHT); + + lv_obj_t * scrl = lv_page_get_scrollable(list_page); + ancient_scrl_signal = lv_obj_get_signal_cb(scrl); + lv_obj_set_signal_cb(scrl, mmi_voicechat_list_scrl_signal); + lv_watch_obj_add_element(list_page); + lv_watch_obj_add_element(scrl); + + + mmi_voicechat_msg_item_info_t * t_voicechat_item_info = &(s_voicechat_info_p->msg_item[0]); + char * file_buf = t_voicechat_item_info->text_data_ptr; + + lv_obj_t * obj = lv_cont_create(list_page, NULL); + lv_obj_set_size(obj, LV_HOR_RES - 20, 50); + lv_cont_set_fit4(obj, LV_FIT_NONE, LV_FIT_NONE, LV_FIT_NONE, LV_FIT_TIGHT); + //lv_cont_set_layout(obj, LV_LAYOUT_COLUMN_LEFT); + lv_obj_add_style(obj, LV_CONT_PART_MAIN, &(ext->style_cont_self)); + lv_obj_align(obj, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + lv_obj_t * label_text = lv_label_create(obj, NULL); + lv_obj_add_style(label_text, LV_LABEL_PART_MAIN, &(ext->style_label_len_self)); + lv_label_set_align(label_text, LV_LABEL_ALIGN_CENTER); + lv_label_set_long_mode(label_text, LV_LABEL_LONG_BREAK); + lv_obj_set_width(label_text, lv_obj_get_width(obj) - 20); + lv_label_set_text(label_text, file_buf); + lv_obj_align(label_text, NULL, LV_ALIGN_IN_LEFT_MID, 10, 0); + + lv_obj_set_adv_hittest(obj, false); + lv_page_focus(list_page, obj, 0); + lv_page_glue_obj(obj, true); + lv_watch_obj_add_element(obj); + + + ext->gif_listening = gif_open(cont, ANIM_VOICECHAT_LISTENING, 0); + if(NULL == ext->gif_listening) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: gif open fail\n", __FUNCTION__, __LINE__); + } + lv_obj_set_style_local_bg_color(ext->gif_listening->container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_align(ext->gif_listening->container, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -LV_VER_RES / 4); + + //label + //lv_obj_t * label_state = lv_label_create(cont, NULL); + //lv_obj_add_style(label_state, LV_LABEL_PART_MAIN, &lv_watch_font20); + //lv_label_set_text_id(label_state, WATCH_TEXT_ID_AIGC_LISTENING); + //lv_label_set_align(label_state, LV_LABEL_ALIGN_CENTER); + //lv_obj_align(label_state, cont, LV_ALIGN_IN_BOTTOM_MID, 0, -20); + + + lv_obj_set_hidden(ext->cont_default, true); + lv_obj_set_hidden(ext->cont_listening, true); + lv_obj_set_hidden(ext->cont_listening_middle, false); + lv_obj_set_hidden(ext->cont_thinking, true); + lv_obj_set_hidden(ext->cont_timeout, true); + lv_obj_set_hidden(ext->cont_list, true); +} + +bool mmi_voicechat_listening_stop(bool is_cancel) +{ + uint32_t duration_ms = 0; + uint32_t size = 0; + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + Hal_Record_Buffer_Stop_Req(&size, &duration_ms); + Hal_Audio_Manage_End_Ind(MMI_VOICECHAT_TTS_AUDIO_PRI); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return false; + + if(true == is_cancel) + { + printf("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + lv_mem_free(ext->record_buffer); + ext->record_buffer = NULL; + ext->record_size = 0; + return false; + } + + if(MMI_VOICECHAT_DATA_RECORD_HEAD_SIZE >= size) + { + printf("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + lv_mem_free(ext->record_buffer); + ext->record_buffer = NULL; + ext->record_size = 0; + return false; + } + ext->record_size = size; + + return true; +} + +void mmi_voicechat_listening_task_cb(lv_task_t * task) +{ + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + if(0 == ext->old_ext.element_click_en) + { + /*sliding to the right, not click button*/ + return; + } + + lv_obj_t * activity_obj; + MCI_EVNET_T event = (MCI_EVNET_T) (task->user_data); + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: event=%d\n", __FUNCTION__, __LINE__, event); + + switch(event) + { + case MCI_EVENT_EOS: + mmi_voicechat_listening_stop(false); + mmi_voicechat_thinking_screen_display(); + break; + + case MCI_EVENT_ERROR: + mmi_voicechat_listening_stop(true); + mmi_voicechat_main_screen_clean(); + break; + + //case MCI_EVENT_INFO: + // break; + + default: + break; + } +} + +void mmi_voicechat_listening_cb(MCI_EVNET_T event, MCI_INFO_T info_type, int32_t value) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: event=%d,type=%d,value=%d\n", __FUNCTION__, __LINE__, event, info_type, value); + + if(MCI_EVENT_INFO != event) + { + //recording_ext->event = event; + lv_task_t * record_task = lv_task_create(mmi_voicechat_listening_task_cb, 10, LV_TASK_PRIO_HIGH, event); + lv_task_once(record_task); + } + else // MCI_EVENT_INFO == event + { + if(MCI_INFO_RECORDER_CUR_SIZE == info_type) + { + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return; + } + + uint32_t sending_size = value - s_voicechat_recording_sent_size; + if(0 >= sending_size) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return; + } + + char * sending_buf = lv_mem_alloc(sending_size + 1); + if(NULL == sending_buf) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + return; + } + _lv_memset_00(sending_buf, sending_size + 1); + _lv_memcpy(sending_buf, ext->record_buffer + s_voicechat_recording_sent_size, sending_size); + + mmi_voicechat_send_trans_audio_msg(sending_buf, sending_size); + lv_mem_free(sending_buf); + s_voicechat_recording_sent_size += sending_size; + } + } +} + +void mmi_voicechat_listening_audio_ctrl_callback(AUDIO_CTRL_PRIORITY priority) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: priority=%d\n", __FUNCTION__, __LINE__, priority); + + if(MMI_VOICECHAT_TTS_AUDIO_PRI == priority) + { + if(false == watch_is_ready()) + { + return; + } + } + else if(MMI_VOICECHAT_TTS_AUDIO_PRI > priority) + { + mmi_voicechat_listening_stop(true); + mmi_voicechat_main_screen_clean(); + } +} + +void mmi_voicechat_listening_screen_display(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_LISTENING; + + s_voicechat_trans_text_end = false; + + // stop audio + Hal_NFFS_File_Play_End(); + Hal_Audio_Manage_End_Ind(MMI_VOICECHAT_TTS_AUDIO_PRI); + + // wb + mmi_voicechat_tts_websocket_close(); + mmi_voicechat_trans_websocket_open(); + + // res + mmi_voicechat_msg_data_clean(); + mmi_voicechat_tts_audio_ll_clean(); + + if(NULL != ext->record_buffer) + { + lv_mem_free(ext->record_buffer); + ext->record_buffer = NULL; + } + ext->record_buffer = (uint8_t *)lv_mem_alloc(MMI_VOICECHAT_DATA_RECORD_SIZE_MAX); + if(NULL != ext->record_buffer) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + _lv_memset_00(ext->record_buffer, MMI_VOICECHAT_DATA_RECORD_SIZE_MAX); + + if(MMI_VOICECHAT_TTS_AUDIO_PRI == Hal_Audio_Manage_Start_Req(MMI_VOICECHAT_TTS_AUDIO_PRI, mmi_voicechat_listening_audio_ctrl_callback)) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_send_trans_start_msg(NULL, 0); + + s_voicechat_recording_sent_size = 0; + Hal_Record_Buffer_With_Format_Req(ext->record_buffer, + MMI_VOICECHAT_DATA_RECORD_SIZE_MAX, + MMI_VOICECHAT_DATA_RECORD_DURATION_MAX * 1000, + mmi_voicechat_listening_cb, + (mci_type_enum)MMI_VOICECHAT_AUDIO_FORMAT); + } + } + + // ui + lv_obj_t * cont = ext->cont_listening; + if(NULL != ext->gif_listening) + { + gif_close(ext->gif_listening); + ext->gif_listening = NULL; + } + lv_obj_clean(cont); + + //label + lv_obj_t * label_state = lv_label_create(cont, NULL); + lv_obj_add_style(label_state, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label_state, WATCH_TEXT_ID_AIGC_LISTENING); + lv_label_set_align(label_state, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label_state, cont, LV_ALIGN_IN_TOP_MID, 0, 20); + + ext->gif_listening = gif_open(cont, ANIM_VOICECHAT_LISTENING, 0); + if(NULL == ext->gif_listening) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: gif open fail\n", __FUNCTION__, __LINE__); + } + lv_obj_set_style_local_bg_color(ext->gif_listening->container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_align(ext->gif_listening->container, NULL, LV_ALIGN_CENTER, 0, 0); + + // signal weak + lv_obj_t * label = lv_label_create(cont, NULL); + lv_obj_add_style(label, LV_OBJ_PART_MAIN, &lv_watch_font26); + lv_label_set_text_id(label, WATCH_TEXT_ID_SIGNAL_WEAK); + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, -10); + lv_obj_set_click(label, false); + ext->listening_signal_weak_label = label; + + lv_obj_set_hidden(ext->cont_default, true); + lv_obj_set_hidden(ext->cont_listening, false); + lv_obj_set_hidden(ext->listening_signal_weak_label, true); + lv_obj_set_hidden(ext->cont_listening_middle, true); + lv_obj_set_hidden(ext->cont_thinking, true); + lv_obj_set_hidden(ext->cont_timeout, true); + lv_obj_set_hidden(ext->cont_list, true); +} + +static void mmi_voicechat_cancel_button_event_cb(lv_obj_t * obj, lv_event_t e) +{ + if(LV_EVENT_CLICKED != e) + return; + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_main_screen_clean(); +} + +static void mmi_voicechat_record_button_event_cb(lv_obj_t * obj, lv_event_t e) +{ + if(LV_EVENT_CLICKED != e) + return; + + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: ui_state=%d\n", __FUNCTION__, __LINE__, s_voicechat_ui_state); + + switch(s_voicechat_ui_state) + { + case MMI_VOICECHAT_UI_STATE_NONE: + mmi_voicechat_listening_screen_display(); + break; + + case MMI_VOICECHAT_UI_STATE_OPEN_FAIL: + mmi_voicechat_main_screen_clean(); + break; + + //case MMI_VOICECHAT_UI_STATE_LISTENING: + //mmi_voicechat_listening_stop(false); + //mmi_voicechat_thinking_screen_display(); + //break; + + case MMI_VOICECHAT_UI_STATE_THINKING: + mmi_voicechat_thinking_screen_clean(); + break; + + case MMI_VOICECHAT_UI_STATE_CONNECT_TIMEOUT: + mmi_voicechat_timeout_screen_clean(); + break; + + case MMI_VOICECHAT_UI_STATE_LIST: + mmi_voicechat_listening_screen_display(); + break; + + default: + break; + } +} + +lv_obj_t * mmi_voicechat_list_msg_item_add(lv_obj_t * list_page, mmi_voicechat_msg_item_info_t * msg_item, char * time_str, uint8_t i) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_obj_t * obj = NULL; + //lv_wechat_msg_list_item_ext_t * list_item_ext = NULL; + //lv_voicechat_list_ext_t * list_page_ext = lv_obj_get_ext_attr(list_page); + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + lv_obj_t * scrl = lv_page_get_scrl(list_page); + lv_obj_t * last_obj = lv_obj_get_child(scrl, NULL); + lv_coord_t obj_y = 0; + + if(NULL != last_obj) + { + obj_y = lv_obj_get_y(last_obj) + lv_obj_get_height(last_obj) + lv_obj_get_style_pad_inner(scrl, LV_STATE_DEFAULT); + } + else + { + obj_y = lv_obj_get_style_pad_top(scrl, LV_STATE_DEFAULT); + } + + uint32_t file_size = msg_item->text_data_size; + char * file_buf = msg_item->text_data_ptr; + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: y=%d,size=%d\n", __FUNCTION__, __LINE__, obj_y, file_size); + + if(0 == msg_item->msg_from) // self + { + obj = lv_cont_create(list_page, NULL); + //list_item_ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_wechat_msg_list_item_ext_t)); + //list_item_ext->item_index = i; + //list_item_ext->unread_img = NULL; + lv_obj_set_size(obj, lv_obj_get_width(list_page) - 40, 50); //lv_obj_set_size(obj, LV_HOR_RES * 2 / 3, 50); // same with voice item + lv_cont_set_fit4(obj, LV_FIT_NONE, LV_FIT_NONE, LV_FIT_NONE, LV_FIT_TIGHT); + //lv_cont_set_layout(obj, LV_LAYOUT_COLUMN_LEFT); + lv_obj_add_style(obj, LV_CONT_PART_MAIN, &(ext->style_cont_self)); + lv_obj_align(obj, scrl, LV_ALIGN_IN_TOP_RIGHT, -10, obj_y); + + lv_obj_t * label_text = lv_label_create(obj, NULL); + lv_obj_add_style(label_text, LV_LABEL_PART_MAIN, &(ext->style_label_len_self)); + lv_label_set_align(label_text, LV_LABEL_ALIGN_LEFT); // LV_LABEL_ALIGN_CENTER); + lv_label_set_long_mode(label_text, LV_LABEL_LONG_BREAK); + lv_obj_set_width(label_text, lv_obj_get_width(obj) - 20); + lv_label_set_text(label_text, file_buf); + lv_obj_align(label_text, obj, LV_ALIGN_IN_LEFT_MID, 10, 0); + } + else + { + obj = lv_cont_create(list_page, NULL); + //list_item_ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_wechat_msg_list_item_ext_t)); + //list_item_ext->item_index = i; + //list_item_ext->unread_img = NULL; + lv_obj_set_size(obj, lv_obj_get_width(list_page) - 40, 50); //lv_obj_set_size(obj, LV_HOR_RES * 2 / 3, 50); // same with voice item + lv_cont_set_fit4(obj, LV_FIT_NONE, LV_FIT_NONE, LV_FIT_NONE, LV_FIT_TIGHT); + //lv_cont_set_layout(obj, LV_LAYOUT_COLUMN_LEFT); + lv_obj_add_style(obj, LV_CONT_PART_MAIN, &(ext->style_cont_other)); + lv_obj_align(obj, scrl, LV_ALIGN_IN_TOP_LEFT, 10, obj_y); + + lv_obj_t * label_text = lv_label_create(obj, NULL); + lv_obj_add_style(label_text, LV_LABEL_PART_MAIN, &(ext->style_label_len_other)); + lv_label_set_align(label_text, LV_LABEL_ALIGN_LEFT); // LV_LABEL_ALIGN_CENTER); + lv_label_set_long_mode(label_text, LV_LABEL_LONG_BREAK); + lv_obj_set_width(label_text, lv_obj_get_width(obj) - 20); + lv_label_set_text(label_text, file_buf); + lv_obj_align(label_text, obj, LV_ALIGN_IN_LEFT_MID, 10, 0); + ext->list_other_label = label_text; + + //if(lv_obj_get_width(list_page) <= (lv_obj_get_y(obj) + lv_obj_get_height(obj))) + //{ + // lv_obj_align(obj, scrl, LV_ALIGN_IN_BOTTOM_LEFT, 10, -10); + //} + } + + //lv_obj_set_click(obj, true); + //lv_obj_set_event_cb(obj, wechat_chat_list_text_item_event_cb); + lv_obj_set_adv_hittest(obj, false); + lv_page_focus(list_page, obj, 0); + lv_page_glue_obj(obj, true); + lv_watch_obj_add_element(obj); + + return obj; +} + +static lv_res_t mmi_voicechat_list_scrl_signal(lv_obj_t * scrl, lv_signal_t sign, void * param) +{ + lv_res_t res; + + /* Include the ancient signal function */ + res = ancient_scrl_signal(scrl, sign, param); + if(res != LV_RES_OK) + return res; + + if(LV_SIGNAL_COORD_CHG == sign) + { + lv_obj_t * list_page = lv_obj_get_parent(scrl); + lv_voicechat_list_ext_t * list_page_ext = (lv_voicechat_list_ext_t *)lv_obj_get_ext_attr(list_page); + if(NULL == list_page_ext) + return; + + if(true == list_page_ext->pressing) + { + list_page_ext->pressing = false; + } + } + + return LV_RES_OK; +} + +lv_obj_t * mmi_voicechat_list_create(lv_obj_t * obj) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_obj_t * list_page = lv_page_create(obj, NULL); + lv_voicechat_list_ext_t * list_page_ext = lv_obj_allocate_ext_attr(list_page, sizeof(lv_voicechat_list_ext_t)); + if(NULL == list_page_ext) + return NULL; + + //lv_obj_set_size(list_page, lv_obj_get_width(obj) - 20, lv_obj_get_height(obj) - 20 - 80); + lv_obj_set_size(list_page, lv_obj_get_width(obj), lv_obj_get_height(obj) - 20 - 80); + lv_page_set_scrollbar_mode(list_page, LV_SCROLLBAR_MODE_OFF); + //lv_list_set_scrollbar_mode(list_page, LV_SCROLLBAR_MODE_AUTO); + lv_obj_set_style_local_bg_opa(list_page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_border_opa(list_page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_outline_width(list_page, LV_PAGE_PART_BG, LV_STATE_DEFAULT, 0); + lv_obj_align(list_page, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + lv_page_set_scrl_layout(list_page, LV_LAYOUT_OFF); + lv_page_set_scrollable_fit2(list_page, LV_FIT_NONE, LV_FIT_TIGHT); + + lv_obj_t * scrl = lv_page_get_scrollable(list_page); + ancient_scrl_signal = lv_obj_get_signal_cb(scrl); + lv_obj_set_signal_cb(scrl, mmi_voicechat_list_scrl_signal); + + lv_watch_obj_add_element(list_page); + lv_watch_obj_add_element(scrl); + + //_lv_memset_00(&(list_page_ext->voice_playing_anim), sizeof(lv_anim_t)); + //list_page_ext->voice_playing_msg_from = 0; + list_page_ext->pressing = false; + + uint8_t i = 0; + uint8_t msg_count = mmi_voicechat_msg_count_get(); + + for(i = 0; i < msg_count; i++) + { + mmi_voicechat_msg_item_info_t * msg_item = &(s_voicechat_info_p->msg_item[i]); + + mmi_voicechat_list_msg_item_add(list_page, msg_item, NULL, i); + } + + //if((lv_obj_get_height(list_page) - lv_obj_get_style_pad_top(list_page, LV_LIST_PART_BG) * 2) > lv_obj_get_height(scrl)) + //{ + // lv_cont_set_layout(scrl, LV_LAYOUT_OFF); + //} + + return list_page; +} + +void mmi_voicechat_list_screen_display(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_LIST; + + // ui + lv_obj_t * cont = ext->cont_list; + lv_obj_clean(cont); + + ext->list = mmi_voicechat_list_create(cont); + + // signal weak + lv_obj_t * label = lv_label_create(cont, NULL); + lv_obj_add_style(label, LV_OBJ_PART_MAIN, &lv_watch_font26); + lv_label_set_text_id(label, WATCH_TEXT_ID_SIGNAL_WEAK); + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, -10); + lv_obj_set_click(label, false); + ext->list_signal_weak_label = label; + + lv_obj_t * imgbtn_cancel = lv_imgbtn_create(cont, NULL); + lv_imgbtn_set_src(imgbtn_cancel, LV_BTN_STATE_RELEASED, ICON_VOICECHAT_CANCEL_BUTTON); + lv_imgbtn_set_src(imgbtn_cancel, LV_BTN_STATE_PRESSED, ICON_VOICECHAT_CANCEL_BUTTON); + lv_obj_set_event_cb(imgbtn_cancel, mmi_voicechat_cancel_button_event_cb); + lv_obj_add_protect(imgbtn_cancel, LV_PROTECT_PRESS_LOST); + lv_watch_obj_add_element(imgbtn_cancel); + lv_obj_align(imgbtn_cancel, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 15, -20); + + lv_obj_t * imgbtn = lv_imgbtn_create(cont, NULL); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_RELEASED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_PRESSED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_obj_set_event_cb(imgbtn, mmi_voicechat_record_button_event_cb); + lv_obj_add_protect(imgbtn, LV_PROTECT_PRESS_LOST); + lv_watch_obj_add_element(imgbtn); + lv_obj_align(imgbtn, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -15, -20); + + lv_obj_t * imgbtn_label = lv_label_create(imgbtn, NULL); + lv_obj_add_style(imgbtn_label, LV_LABEL_PART_MAIN, &lv_watch_font26); + lv_label_set_align(imgbtn_label, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_id(imgbtn_label, WATCH_TEXT_ID_AIGC_CONTINUE); + lv_obj_align(imgbtn_label, NULL, LV_ALIGN_CENTER, 0, 0); + + lv_obj_set_hidden(ext->cont_default, true); + lv_obj_set_hidden(ext->cont_listening, true); + lv_obj_set_hidden(ext->cont_listening_middle, true); + lv_obj_set_hidden(ext->cont_thinking, true); + lv_obj_set_hidden(ext->cont_timeout, true); + lv_obj_set_hidden(ext->cont_list, false); + lv_obj_set_hidden(ext->list_signal_weak_label, true); +} + +static void mmi_voicechat_default_screen_display(void) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_NONE; + + // ui + lv_obj_t * cont = ext->cont_default; + lv_obj_clean(cont); + + lv_obj_t * label_state = lv_label_create(cont, NULL); + lv_obj_add_style(label_state, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label_state, WATCH_TEXT_ID_VOICECHAT); + lv_label_set_align(label_state, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label_state, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + lv_obj_t * img = lv_img_create(cont, NULL); + lv_img_set_src(img, ICON_VOICECHAT_DEFAULT); + lv_obj_set_click(img, false); + lv_obj_align(img, NULL, LV_ALIGN_CENTER, 0, -10); + + lv_obj_t * imgbtn = lv_imgbtn_create(cont, NULL); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_RELEASED, ICON_VOICECHAT_RECORD_BUTTON_DEFAULT); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_PRESSED, ICON_VOICECHAT_RECORD_BUTTON_DEFAULT); + lv_obj_set_event_cb(imgbtn, mmi_voicechat_record_button_event_cb); + lv_obj_add_protect(imgbtn, LV_PROTECT_PRESS_LOST); + lv_watch_obj_add_element(imgbtn); + lv_obj_align(imgbtn, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -20); + + lv_obj_t * imgbtn_label = lv_label_create(imgbtn, NULL); + lv_obj_add_style(imgbtn_label, LV_LABEL_PART_MAIN, &lv_watch_font26); + lv_label_set_align(imgbtn_label, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_id(imgbtn_label, WATCH_TEXT_ID_AIGC_CONVERSATION); + lv_obj_align(imgbtn_label, NULL, LV_ALIGN_CENTER, 0, 0); + + lv_obj_set_hidden(ext->cont_default, false); + lv_obj_set_hidden(ext->cont_listening, true); + lv_obj_set_hidden(ext->cont_listening_middle, true); + lv_obj_set_hidden(ext->cont_thinking, true); + lv_obj_set_hidden(ext->cont_timeout, true); + lv_obj_set_hidden(ext->cont_list, true); +} + +static void mmi_voicechat_no_network_screen_display(lv_obj_t * obj) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = (lv_voicechat_ext_t *)mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return ; + + // ui + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_OPEN_FAIL; + + lv_obj_t * cont = lv_cont_create(obj, NULL); + lv_obj_set_size(cont, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont); + + //label + lv_obj_t * label_state = lv_label_create(cont, NULL); + lv_obj_add_style(label_state, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label_state, WATCH_TEXT_ID_VOICECHAT); + lv_label_set_align(label_state, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label_state, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); + + lv_obj_t * img = lv_img_create(cont, NULL); + lv_img_set_src(img, ICON_VOICECHAT_PROMPT); + lv_obj_set_click(img, false); + lv_obj_align(img, NULL, LV_ALIGN_IN_TOP_MID, 0, 70); + + lv_obj_t * label = lv_label_create(cont, NULL); + lv_obj_add_style(label, LV_LABEL_PART_MAIN, &lv_watch_font20); + lv_label_set_text_id(label, WATCH_TEXT_ID_AIGC_OPEN_FAIL); + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, img, LV_ALIGN_OUT_BOTTOM_MID, 0, 25); + + lv_obj_t * imgbtn = lv_imgbtn_create(cont, NULL); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_RELEASED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_imgbtn_set_src(imgbtn, LV_BTN_STATE_PRESSED, ICON_VOICECHAT_RECORD_BUTTON_PRESSED); + lv_obj_set_event_cb(imgbtn, mmi_voicechat_record_button_event_cb); + lv_obj_align(imgbtn, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -20); + + lv_obj_t * imgbtn_label = lv_label_create(imgbtn, NULL); + lv_obj_add_style(imgbtn_label, LV_LABEL_PART_MAIN, &lv_watch_font26); + lv_label_set_align(imgbtn_label, LV_LABEL_ALIGN_CENTER); + lv_label_set_text_id(imgbtn_label, WATCH_TEXT_ID_OK); + lv_obj_align(imgbtn_label, NULL, LV_ALIGN_CENTER, 0, 0); +} + +void mmi_voicechat_main_screen_refresh(void) +{ + printf("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + lv_voicechat_ext_t * ext = mmi_voicechat_actId_ext_get(ACT_ID_VOICECHAT_MAIN); + if(NULL == ext) + return; + + mmi_voicechat_list_set_slide_enable(&ext->old_ext, true); + + if(NULL != ext->thinking_task_p) + { + lv_task_del(ext->thinking_task_p); + ext->thinking_task_p = NULL; + } + + uint8_t msg_count = mmi_voicechat_msg_count_get(); + //mmi_voicechat_list_create(ext->cont, ext); + if(0 == msg_count) + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_default_screen_display(); + } + else + { + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + mmi_voicechat_list_screen_display(); + } +} + +lv_obj_t * mmi_voicechat_main_create(lv_obj_t * activity_obj) +{ + VOICECHAT_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + + if(activity_obj == NULL) + { + lv_watch_activity_ext_t activity_ext; + + _lv_memset_00(&activity_ext, sizeof(lv_watch_activity_ext_t)); + activity_ext.actId = ACT_ID_VOICECHAT_MAIN; + activity_ext.create = (lv_watch_activity_create_f_t)mmi_voicechat_main_create; //NULL; + activity_ext.prepare_destory = mmi_voicechat_main_prepare_destory; + activity_obj = lv_watch_creat_activity_obj(&activity_ext); + LV_ASSERT_MEM(activity_obj); + } + +#ifdef __MMI_ZHSX_SUPPORT__ + s_is_ACT_ID_VOICECHAT_MAIN = true; +#endif + + lv_obj_t * obj = lv_watch_obj_create(activity_obj); + if(NULL == obj) + return NULL; + /*Allocate the tab type specific extended data*/ + lv_voicechat_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_voicechat_ext_t)); + if(NULL == ext) + return NULL; + + ext->cont_default = NULL; + ext->cont_listening = NULL; + ext->cont_thinking = NULL; + ext->cont_timeout = NULL; + ext->cont_list = NULL; + + ext->list = NULL; + ext->record_buffer = NULL; + ext->record_size = 0; + ext->thinking_task_p = NULL; + ext->gif_listening = NULL; + ext->gif_thinking = NULL; + + s_voicechat_ui_state = MMI_VOICECHAT_UI_STATE_NONE; + + if(false == watch_modem_sim_present_check_req() // no sim + //|| (MMI_MODEM_SIGNAL_BAR_0 == watch_modem_get_signal_bar_req()) // no signal + //|| (false == watch_modem_sim_present_check_req()) // not activated + ) + { + mmi_voicechat_no_network_screen_display(obj); + + return obj; + } + + // data task + mmi_voicechat_data_task_create(); + watch_set_suspend_enable(false, ACT_ID_VOICECHAT_MAIN, 0); + + // cont_default + lv_obj_t * cont_default = lv_cont_create(obj, NULL); + lv_obj_set_size(cont_default, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont_default, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont_default, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont_default); + ext->cont_default = cont_default; + + // cont_listening + lv_obj_t * cont_listening = lv_cont_create(obj, NULL); + lv_obj_set_size(cont_listening, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont_listening, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont_listening, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont_listening); + ext->cont_listening = cont_listening; + + // cont_listening middle + lv_obj_t * cont_listening_middle = lv_cont_create(obj, NULL); + lv_obj_set_size(cont_listening_middle, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont_listening_middle, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont_listening_middle, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont_listening_middle); + ext->cont_listening_middle = cont_listening_middle; + + // cont_thinking + lv_obj_t * cont_thinking = lv_cont_create(obj, NULL); + lv_obj_set_size(cont_thinking, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont_thinking, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont_thinking, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont_thinking); + ext->cont_thinking = cont_thinking; + + // cont_timeout + lv_obj_t * cont_timeout = lv_cont_create(obj, NULL); + lv_obj_set_size(cont_timeout, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont_timeout, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont_timeout, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont_timeout); + ext->cont_timeout = cont_timeout; + + // cont_list + lv_obj_t * cont_list = lv_cont_create(obj, NULL); + lv_obj_set_size(cont_list, lv_obj_get_width(obj), lv_obj_get_height(obj)); + lv_obj_align(cont_list, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(cont_list, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_watch_obj_add_element(cont_list); + ext->cont_list = cont_list; + + // style + mmi_voicechat_lv_style_set(); + + mmi_voicechat_default_screen_display(); + + return obj; +} + +void mmi_voicechat_create_event_cb(lv_obj_t * btn, lv_event_t e) +{ + if(LV_EVENT_CLICKED == e) + { + // free resource + mmi_voicechat_msg_data_clean(); + mmi_voicechat_tts_audio_ll_init(); + mmi_voicechat_tts_audio_ll_clean(); + + lv_watch_png_cache_all_free(); + lv_obj_t * obj = mmi_voicechat_main_create(NULL); + LV_ASSERT_MEM(obj); + } +} + +#endif + diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_ui.h b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_ui.h new file mode 100644 index 00000000..136fdb01 --- /dev/null +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/custom_function/mmi_voicechat_ui.h @@ -0,0 +1,164 @@ + + + +#ifndef __MMI_VOICECHAT_UI_H__ +#define __MMI_VOICECHAT_UI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LV_CONF_INCLUDE_SIMPLE +#include "lvgl.h" +#include "lv_watch_conf.h" +#else +#include "../../../lvgl/lvgl.h" +#include "../../../lv_watch_conf.h" +#endif + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + + +#define __MMI_VOICECHAT_DEBUG__ +#ifdef __MMI_VOICECHAT_DEBUG__ +#define VOICECHAT_DEBUG_PRINTF(fmt, ...) printf("[VOICECHAT]"fmt, ##__VA_ARGS__) +//#define VOICECHAT_DEBUG_PRINTF(fmt, ...) CPUartLogPrintf("[VOICECHAT]"fmt, ##__VA_ARGS__) +//#define VOICECHAT_DEBUG_PRINTF(fmt, ...) cplog_printf("[VOICECHAT]"fmt, ##__VA_ARGS__) +#else +#define VOICECHAT_DEBUG_PRINTF(fmt, ...) +#endif + + +//#define MMI_VOICECHAT_DEBUG_TO_FILE +#ifdef MMI_VOICECHAT_DEBUG_TO_FILE +#define VOICECHAT_RECV_TRANS_FILE "C:/aigc_trans.txt" +#define VOICECHAT_RECV_TRANS_RESULT_FILE "C:/aigc_trans_result.txt" +#define VOICECHAT_RECV_CHAT_FILE "C:/aigc_chat.txt" +#define VOICECHAT_RECV_CHAT_RESULT_FILE "C:/aigc_chat_result.txt" +#define VOICECHAT_RECV_TTS_FILE "C:/aigc_tts.txt" +#define VOICECHAT_SEND_TTS_TEXT_FILE "C:/aigc_tts_text.txt" +#endif + + + +#define MMI_VOICECHAT_AUDIO_FORMAT (3) // 7-pcm8; 3-amr +//#define MMI_VOICECHAT_AUDIO_FORMAT_STR (".wav") // ".amr" + +#if 1 // amr +#define MMI_VOICECHAT_DATA_RECORD_HEAD_SIZE (6) +#define MMI_VOICECHAT_DATA_RECORD_DURATION_MAX (60) // seconds +#define MMI_VOICECHAT_DATA_RECORD_SIZE_MAX ((MMI_VOICECHAT_DATA_RECORD_DURATION_MAX + 2) * HAL_AMR_BUFSIZE_PER_SECOND + MMI_VOICECHAT_DATA_RECORD_HEAD_SIZE) +#else // pcm +#define MMI_VOICECHAT_DATA_RECORD_HEAD_SIZE (44) +#define MMI_VOICECHAT_DATA_RECORD_DURATION_MAX (10) // seconds +#define MMI_VOICECHAT_DATA_RECORD_SIZE_MAX (MMI_VOICECHAT_DATA_RECORD_DURATION_MAX * 16000 + MMI_VOICECHAT_DATA_RECORD_HEAD_SIZE) +#endif + +#define MMI_VOICECHAT_TTS_AUDIO_PRI (AUDIO_CTRL_PRIORITY_2) + + +#define MMI_VOICECHAT_MSG_NUM_MAX (2) +//#define MMI_VOICECHAT_DATA_FILE_NAME_MAX (64) // (LV_FS_MAX_PATH_LENGTH / 2) + +typedef struct +{ + uint8_t msg_from; // 0-slef; 1-other + //hal_rtc_t msg_time; + void * text_data_ptr; + uint32_t text_data_size; + void * audio_data_ptr; + uint32_t audio_data_size; +} mmi_voicechat_msg_item_info_t; + +typedef struct +{ + uint8_t msg_count; + mmi_voicechat_msg_item_info_t msg_item[MMI_VOICECHAT_MSG_NUM_MAX]; +} mmi_voicechat_msg_info_t; + +typedef struct +{ + void * audio_data_ptr; + uint32_t audio_data_size; +} mmi_voicechat_tts_audio_ll_t; + +typedef struct +{ + lv_watch_obj_ext_t old_ext; + lv_obj_t * unread_img; + uint8_t item_index; +} lv_voicechat_list_item_ext_t; + +typedef struct { + lv_page_ext_t old_ext; + //lv_anim_t voice_playing_anim; + //uint8_t voice_playing_msg_from; // 0-slef; 1-other + bool pressing; + //lv_style_t style_cont_self; + //lv_style_t style_cont_other; + //lv_style_t style_label_time; + //lv_style_t style_label_len_other; + //lv_style_t style_label_len_self; +} lv_voicechat_list_ext_t; + +typedef struct +{ + lv_watch_obj_ext_t old_ext; + + //TIMER_ID delete_timer_id; + lv_obj_t * cont_default; + lv_obj_t * cont_listening; + lv_obj_t * listening_signal_weak_label; + lv_obj_t * cont_listening_middle; + lv_obj_t * cont_thinking; + lv_obj_t * cont_timeout; + lv_obj_t * cont_list; + lv_obj_t * list; // chat list + lv_obj_t * list_signal_weak_label; + lv_obj_t * list_other_label; + + lv_style_t style_cont_self; + lv_style_t style_cont_other; + //lv_style_t style_label_time; + lv_style_t style_label_len_other; + lv_style_t style_label_len_self; + + MCI_EVNET_T event; + uint8_t * record_buffer; + uint32_t record_size; + + lv_task_t * thinking_task_p; + + gif_info_t * gif_listening; + gif_info_t * gif_thinking; +}lv_voicechat_ext_t; + +typedef enum +{ + MMI_VOICECHAT_UI_STATE_NONE, + MMI_VOICECHAT_UI_STATE_OPEN_FAIL, + MMI_VOICECHAT_UI_STATE_LISTENING, + MMI_VOICECHAT_UI_STATE_LISTENING_MIDDLE, + MMI_VOICECHAT_UI_STATE_THINKING, + MMI_VOICECHAT_UI_STATE_CONNECT_TIMEOUT, + MMI_VOICECHAT_UI_STATE_LIST, + + MMI_VOICECHAT_UI_STATE_MAX +}MMI_VOICECHAT_UI_STATE_E; + + + +char * mmi_voicechat_trans_result_text_get(uint32_t * data_len); +bool mmi_voicechat_trans_result_text_store(char * data_buff, uint32_t data_len, bool is_end); +bool mmi_voicechat_chat_result_text_store(char * data_buff, uint32_t data_len); +void mmi_voicechat_create_event_cb(lv_obj_t * btn, lv_event_t e); +bool mmi_is_ACT_ID_VOICECHAT_MAIN(void); + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/2.sdk/sdk/gui/lv_watch/lv_apps/primary_menu/primary_menu_data.c b/2.sdk/sdk/gui/lv_watch/lv_apps/primary_menu/primary_menu_data.c index 69eefdba..1db16c0d 100644 --- a/2.sdk/sdk/gui/lv_watch/lv_apps/primary_menu/primary_menu_data.c +++ b/2.sdk/sdk/gui/lv_watch/lv_apps/primary_menu/primary_menu_data.c @@ -45,6 +45,9 @@ static watch_app_info_t s_main_menu_four_grid[] = #ifdef __MMI_CUSTOM_AIGC_SUPPORT__ { ICON_AIGC_ASSISTANT, WATCH_TEXT_ID_AIGC_ASSISTANT, mmi_aigc_create_event_cb }, #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + { ICON_VOICECHAT, WATCH_TEXT_ID_VOICECHAT, mmi_voicechat_create_event_cb }, +#endif #if USE_LV_WATCH_CAMERA != 0 { ICON_CAMERA, WATCH_TEXT_ID_CAMERA, camera_create_btn_event_cb }, { ICON_ALBUM, WATCH_TEXT_ID_ALBUM, album_create_event_cb }, @@ -168,6 +171,9 @@ static watch_app_info_t s_main_menu_list[] = #ifdef __MMI_CUSTOM_AIGC_SUPPORT__ { ICON_AIGC_ASSISTANT_LIST, WATCH_TEXT_ID_AIGC_ASSISTANT, mmi_aigc_create_event_cb }, #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + { ICON_VOICECHAT_LIST, WATCH_TEXT_ID_VOICECHAT, mmi_voicechat_create_event_cb }, +#endif #if USE_LV_WATCH_CAMERA != 0 { ICON_CAMERA_LIST, WATCH_TEXT_ID_CAMERA, camera_create_btn_event_cb }, { ICON_ALBUM_LIST, WATCH_TEXT_ID_ALBUM, album_create_event_cb }, diff --git a/2.sdk/sdk/gui/lv_watch/lv_watch_res.h b/2.sdk/sdk/gui/lv_watch/lv_watch_res.h index 9852904f..fe599f60 100644 --- a/2.sdk/sdk/gui/lv_watch/lv_watch_res.h +++ b/2.sdk/sdk/gui/lv_watch/lv_watch_res.h @@ -231,6 +231,9 @@ LV_IMG_DECLARE(img_poweron_logo); #ifdef __MMI_CUSTOM_AIGC_SUPPORT__ #define ICON_AIGC_ASSISTANT "R:/png/primary_function/ICON_AIGC_ASSISTANT.png" #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ +#define ICON_VOICECHAT "R:/png/primary_function/ICON_VOICECHAT.png" +#endif #ifdef __MMI_CUSTOM_BEI_KE_RUI_SHENG__ #define ICON_AI_TALK "R:/png/primary_function/ICON_AI_TALK.png" #endif @@ -298,6 +301,9 @@ LV_IMG_DECLARE(img_poweron_logo); #ifdef __MMI_CUSTOM_AIGC_SUPPORT__ #define ICON_AIGC_ASSISTANT_LIST "R:/png/primary_function/list/ICON_AIGC_ASSISTANT.png" #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ +#define ICON_VOICECHAT_LIST "R:/png/primary_function/list/ICON_VOICECHAT_LIST.png" +#endif #if USE_LV_WATCH_WEATHER != 0 #ifdef __MMI_WEATHER_MENU_SUPPORT__ @@ -1069,6 +1075,16 @@ LV_IMG_DECLARE(img_poweron_logo); #define ANIM_AIGC_THINKING "R:/png/mmi_aigc/ANIM_AIGC_THINKING.gif" #endif +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ +#define ICON_VOICECHAT_RECORD_BUTTON_DEFAULT "R:/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_DEFAULT.png" +#define ICON_VOICECHAT_RECORD_BUTTON_PRESSED "R:/png/voice_chat/ICON_VOICECHAT_RECORD_BUTTON_PRESSED.png" +#define ICON_VOICECHAT_PROMPT "R:/png/voice_chat/ICON_VOICECHAT_PROMPT.png" +#define ICON_VOICECHAT_DEFAULT "R:/png/voice_chat/ICON_VOICECHAT_DEFAULT.png" +//#define ICON_VOICECHAT_THINKING "R:/png/voice_chat/ICON_VOICECHAT_THINKING.png" +#define ICON_VOICECHAT_CANCEL_BUTTON "R:/png/voice_chat/ICON_VOICECHAT_CANCEL_BUTTON.png" +#define ANIM_VOICECHAT_LISTENING "R:/png/voice_chat/ANIM_VOICECHAT_LISTENING.gif" +#define ANIM_VOICECHAT_THINKING "R:/png/voice_chat/ANIM_VOICECHAT_THINKING.gif" +#endif #endif diff --git a/2.sdk/sdk/product/craneg_modem/pcac/wsclient/build/wsclient.mak b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/build/wsclient.mak index 3406e6f0..59c739ec 100644 --- a/2.sdk/sdk/product/craneg_modem/pcac/wsclient/build/wsclient.mak +++ b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/build/wsclient.mak @@ -71,7 +71,9 @@ PACKAGE_SRC_FILES = \ mmi_aigc_chat_websocket_client.c \ mmi_aigc_chat_websocket.c \ mmi_aigc_tts_websocket_client.c \ - mmi_aigc_tts_websocket.c + mmi_aigc_tts_websocket.c \ + mmi_voicechat_websocket.c \ + mmi_voicechat_websocket_client.c # These are the tool flags specific to the ci_stub package only. diff --git a/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket.h b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket.h new file mode 100644 index 00000000..349dd848 --- /dev/null +++ b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket.h @@ -0,0 +1,39 @@ + + + +#ifndef __MMI_VOICECHAT_WEBSOCKET_H__ +#define __MMI_VOICECHAT_WEBSOCKET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../../../config/watch/lv_watch_conf_CUSTOM.h" + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + + +#define __MMI_VOICECHAT_WB_DEBUG__ +#ifdef __MMI_VOICECHAT_WB_DEBUG__ +//#define VOICECHAT_WB_DEBUG_PRINTF(fmt, ...) printf("[VOICECHAT_WB]"fmt, ##__VA_ARGS__) +//#define VOICECHAT_WB_DEBUG_PRINTF(fmt, ...) CPUartLogPrintf("[VOICECHAT_WB]"fmt, ##__VA_ARGS__) +#define VOICECHAT_WB_DEBUG_PRINTF(fmt, ...) cplog_printf("[VOICECHAT_WB]"fmt, ##__VA_ARGS__) +#else +#define VOICECHAT_WB_DEBUG_PRINTF(fmt, ...) +#endif + + +int mmi_voicechat_websocket_send_text_data(char * data_ptr, int data_len); +int mmi_voicechat_websocket_send_binary_data(char * data_ptr, int data_len); +void mmi_voicechat_websocket_app_start(void); +void mmi_voicechat_websocket_app_stop(void); + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket_client.h b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket_client.h new file mode 100644 index 00000000..e9cfaf3b --- /dev/null +++ b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/inc/mmi_voicechat_websocket_client.h @@ -0,0 +1,291 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// 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 + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __MMI_VOICECHAT_WEBSOCKET_CLIENT_H__ +#define __MMI_VOICECHAT_WEBSOCKET_CLIENT_H__ + + +#include +#include +#include +#include "web_esp_transport_ws.h" +#include "esp_err.h" +#include "web_esp_transport.h" +#include "osa_old_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../../../config/watch/lv_watch_conf_CUSTOM.h" + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + +typedef unsigned long UINT32; + +#define sim_portTICK_RATE_MS 1000 +#define sim_portTICK_PERIOD_MS 1000 + +//ESP_EVENT_DECLARE_BASE(WEBSOCKET_EVENTS); // declaration of the task events family + +/****************************************** + function declared in here + *****************************************/ +extern char* strdup(const char* str); +extern void free( void *p ); +extern void *malloc( size_t Size ); +extern void *calloc( size_t nItems, size_t itemSize ); +//extern int strtol(const char *p1, char **p2, int base); + +typedef struct sim_esp_websocket_client *sim_esp_websocket_client_handle_t; +typedef void (*sim_esp_event_handler_t)(int32_t event_id, void* event_data); /**< function called when an event is posted to the queue */ + +/** + * @brief Websocket Client events id + */ +typedef enum { + WEBSOCKET_EVENT_ANY = -1, + WEBSOCKET_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */ + WEBSOCKET_EVENT_CONNECTED, /*!< Once the Websocket has been connected to the server, no data exchange has been performed */ + WEBSOCKET_EVENT_DISCONNECTED, /*!< The connection has been disconnected */ + WEBSOCKET_EVENT_DATA, /*!< When receiving data from the server, possibly multiple portions of the packet */ + WEBSOCKET_EVENT_CLOSED, + WEBSOCKET_EVENT_MAX +} sim_esp_websocket_event_id_t; + +/** + * @brief Websocket event data + */ +typedef struct { + char *data_ptr; /*!< Data pointer */ + int data_len; /*!< Data length */ + uint8_t op_code; /*!< Received opcode */ + sim_esp_websocket_client_handle_t client; /*!< sim_esp_websocket_client_handle_t context */ + void *user_context; /*!< user_data context, from sim_esp_websocket_client_config_t user_data */ + int payload_len; /*!< Total payload length, payloads exceeding buffer will be posted through multiple events */ + int payload_offset; /*!< Actual offset for the data associated with this event */ + sim_esp_websocket_event_id_t event; +} sim_esp_websocket_event_data_t; + +typedef struct { + UINT32 task_stack; + int task_prio; + char *uri; + char *p_host; + char host[64]; + char *p_path; + char path[1024]; + char scheme[16]; + char *username; + char *password; + int port; + bool auto_reconnect; + void *user_context; + int network_timeout_ms; + char *subprotocol; +} sim_websocket_config_storage_t; + +typedef enum { + WEBSOCKET_STATE_ERROR = -1, + WEBSOCKET_STATE_UNKNOW = 0, + WEBSOCKET_STATE_INIT, + WEBSOCKET_STATE_CONNECTED, + WEBSOCKET_STATE_WAIT_TIMEOUT, + WEBSOCKET_STATE_CLOSING, +} sim_websocket_client_state_t; + +struct sim_esp_websocket_client { + sim_esp_event_handler_t handler; + wb_esp_transport_list_handle_t transport_list; + wb_esp_transport_handle_t transport; + sim_websocket_config_storage_t *config; + sim_websocket_client_state_t state; + OSAMutexRef lock; + UINT32 keepalive_tick_ms; + UINT32 reconnect_tick_ms; + UINT32 ping_tick_ms; + int wait_timeout_ms; + int auto_reconnect; + char *rx_buffer; + char *tx_buffer; + int buffer_size; + ws_transport_opcodes_t last_opcode; + int payload_len; + int payload_offset; +}; + +/** + * @brief Websocket Client transport + */ +typedef enum { + WEBSOCKET_TRANSPORT_UNKNOWN = 0x0, /*!< Transport unknown */ + WEBSOCKET_TRANSPORT_OVER_TCP, /*!< Transport over tcp */ + WEBSOCKET_TRANSPORT_OVER_SSL, /*!< Transport over ssl */ +} sim_esp_websocket_transport_t; + +/** + * @brief Websocket client setup configuration + */ +typedef struct { + const char *uri; /*!< Websocket URI, the information on the URI can be overrides the other fields below, if any */ + const char *host; /*!< Domain or IP as string */ + int port; /*!< Port to connect, default depend on sim_esp_websocket_transport_t (80 or 443) */ + const char *username; /*!< Using for Http authentication - Not supported for now */ + const char *password; /*!< Using for Http authentication - Not supported for now */ + const char *path; /*!< HTTP Path, if not set, default is `/` */ + bool disable_auto_reconnect; /*!< Disable the automatic reconnect function when disconnected */ + void *user_context; /*!< HTTP user data context */ + int task_prio; /*!< Websocket task priority */ + int task_stack; /*!< Websocket task stack */ + int buffer_size; /*!< Websocket buffer size */ + const char *cert_pem; /*!< SSL Certification, PEM format as string, if the client requires to verify server */ + sim_esp_websocket_transport_t transport; /*!< Websocket transport type, see `sim_esp_websocket_transport_t */ + char *subprotocol; /*!< Websocket subprotocol */ +} sim_esp_websocket_client_config_t; + +/** + * @brief Start a Websocket session + * This function must be the first function to call, + * and it returns a sim_esp_websocket_client_handle_t that you must use as input to other functions in the interface. + * This call MUST have a corresponding call to sim_esp_websocket_client_destroy when the operation is complete. + * + * @param[in] config The configuration + * + * @return + * - `sim_esp_websocket_client_handle_t` + * - NULL if any errors + */ +sim_esp_websocket_client_handle_t voicechat_websocket_client_init(const sim_esp_websocket_client_config_t *config); + +/** + * @brief Set URL for client, when performing this behavior, the options in the URL will replace the old ones + * Must stop the WebSocket client before set URI if the client has been connected + * + * @param[in] client The client + * @param[in] uri The uri + * + * @return esp_err_t + */ +esp_err_t voicechat_websocket_client_set_uri(sim_esp_websocket_client_handle_t client, const char *uri); + +/** + * @brief Open the WebSocket connection + * + * @param[in] client The client + * + * @return esp_err_t + */ +esp_err_t voicechat_websocket_client_start(sim_esp_websocket_client_handle_t client); + +/** + * @brief Close the WebSocket connection + * + * @param[in] client The client + * + * @return esp_err_t + */ +esp_err_t voicechat_websocket_client_stop(sim_esp_websocket_client_handle_t client); + +/** + * @brief Destroy the WebSocket connection and free all resources. + * This function must be the last function to call for an session. + * It is the opposite of the sim_esp_websocket_client_init function and must be called with the same handle as input that a esp_websocket_client_init call returned. + * This might close all connections this handle has used. + * + * @param[in] client The client + * + * @return esp_err_t + */ +esp_err_t voicechat_websocket_client_destroy(sim_esp_websocket_client_handle_t client); + +/** + * @brief Generic write data to the WebSocket connection; defaults to binary send + * + * @param[in] client The client + * @param[in] data The data + * @param[in] len The length + * @param[in] timeout Write data timeout + * + * @return + * - Number of data was sent + * - (-1) if any errors + */ +int voicechat_websocket_client_send(sim_esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout); + +/** + * @brief Write binary data to the WebSocket connection (data send with WS OPCODE=02, i.e. binary) + * + * @param[in] client The client + * @param[in] data The data + * @param[in] len The length + * @param[in] timeout Write data timeout + * + * @return + * - Number of data was sent + * - (-1) if any errors + */ +int voicechat_websocket_client_send_bin(sim_esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout); + +static int voicechat_websocket_client_send_close(sim_esp_websocket_client_handle_t client, int code, const char *additional_data, int total_len, TickType_t timeout); + +static int voicechat_websocket_client_close_with_optional_body(sim_esp_websocket_client_handle_t client, bool send_body, int code, const char *data, int len, TickType_t timeout); + +int voicechat_websocket_client_close_with_code(sim_esp_websocket_client_handle_t client, int code, const char *data, int len, TickType_t timeout); + +int voicechat_websocket_client_close(sim_esp_websocket_client_handle_t client, TickType_t timeout); + +/** + * @brief Write textual data to the WebSocket connection (data send with WS OPCODE=01, i.e. text) + * + * @param[in] client The client + * @param[in] data The data + * @param[in] len The length + * @param[in] timeout Write data timeout + * + * @return + * - Number of data was sent + * - (-1) if any errors + */ +int voicechat_websocket_client_send_text(sim_esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout); + +/** + * @brief Check the WebSocket connection status + * + * @param[in] client The client handle + * + * @return + * - true + * - false + */ +bool voicechat_websocket_client_is_connected(sim_esp_websocket_client_handle_t client); + +/** + * @brief Register the Websocket Events + * + * @param client The client handle + * @param event The event id + * @param event_handler The callback function + * @param event_handler_arg User context + * @return esp_err_t + */ +esp_err_t voicechat_websocket_register_events(sim_esp_websocket_client_handle_t client, + sim_esp_event_handler_t event_handler); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/src/mmi_voicechat_websocket.c b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/src/mmi_voicechat_websocket.c new file mode 100644 index 00000000..331bd33f --- /dev/null +++ b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/src/mmi_voicechat_websocket.c @@ -0,0 +1,165 @@ + + + +#include "uart.h" +#include "mmi_voicechat_websocket_client.h" +#include "mmi_voicechat_websocket.h" + + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + +#define MMI_VOICECHAT_WEBSOCKET_URI "wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1" + +static sim_esp_websocket_client_handle_t s_voicechat_ws_client_p = NULL; + +extern void mmi_voicechat_websocket_recv_data_handler(char * data_ptr, int data_len, int payload_len, int payload_offset); + + + +int mmi_voicechat_websocket_send_text_data(char * data_ptr, int data_len) +{ + int ret = -1; + + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: client_p=%#X\n", __FUNCTION__, __LINE__, s_voicechat_ws_client_p); + if(NULL == s_voicechat_ws_client_p) + { + return ret; + } + + ret = voicechat_websocket_client_send_text(s_voicechat_ws_client_p, data_ptr, data_len, portMAX_DELAY); + if (0 > ret) + { + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + } + + return ret; +} + +int mmi_voicechat_websocket_send_binary_data(char * data_ptr, int data_len) +{ + int ret = -1; + + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: client_p=%#X\n", __FUNCTION__, __LINE__, s_voicechat_ws_client_p); + if(NULL == s_voicechat_ws_client_p) + { + return ret; + } + + ret = voicechat_websocket_client_send_bin(s_voicechat_ws_client_p, data_ptr, data_len, portMAX_DELAY); + if (0 > ret) + { + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: \n", __FUNCTION__, __LINE__); + } + + return ret; +} + +static void mmi_voicechat_websocket_event_handler(int32_t event_id, void *event_data) +{ + sim_esp_websocket_event_data_t *data = (sim_esp_websocket_event_data_t *)event_data; + + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: event_id=%d\n", __FUNCTION__, __LINE__, event_id); + switch (event_id) + { + case WEBSOCKET_EVENT_CONNECTED: + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: WEBSOCKET_EVENT_CONNECTED\n", __LINE__); + break; + + case WEBSOCKET_EVENT_DISCONNECTED: + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: WEBSOCKET_EVENT_DISCONNECTED\n", __LINE__); + break; + + case WEBSOCKET_EVENT_DATA: + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: WEBSOCKET_EVENT_DATA\n", __LINE__); + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG]: data opcode=%d,data len=%d", data->op_code, data->data_len); + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG]: Total payload len=%d,current payload offset=%d\r\n", data->payload_len, data->payload_offset); + if (data->op_code == 0x08 && data->data_len == 2) { + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG]: Received closed message with code=%d", 256*data->data_ptr[0] + data->data_ptr[1]); + } + else + { + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG]: Received=%.*s", data->data_len, (char *)data->data_ptr); + mmi_voicechat_websocket_recv_data_handler(data->data_ptr, data->data_len, data->payload_len, data->payload_offset); + } + //OSATimerStart(shutdown_signal_timer, portMAX_DELAY, 0, shutdown_signaler, 0); + break; + + case WEBSOCKET_EVENT_ERROR: + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: WEBSOCKET_EVENT_ERROR\n", __LINE__); + break; + + case WEBSOCKET_EVENT_CLOSED: + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: WEBSOCKET_EVENT_CLOSED\n", __LINE__); + break; + + default: + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%d]: default\n", __LINE__); + break; + } + + if (NULL != data) + { + if (NULL != data->data_ptr) + { + free(data->data_ptr); + data->data_ptr = NULL; + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free data ptr\n", __FUNCTION__, __LINE__); + } + + free(data); + data = NULL; + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: free data\n", __FUNCTION__, __LINE__); + } +} + +void mmi_voicechat_websocket_app_start(void) +{ + mmi_voicechat_websocket_app_stop(); + + OS_STATUS status = 0; + int ret = 0; + sim_esp_websocket_client_config_t websocket_cfg = {0}; + + websocket_cfg.uri = MMI_VOICECHAT_WEBSOCKET_URI; + websocket_cfg.transport == WEBSOCKET_TRANSPORT_OVER_SSL; + + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: url=%s\n", __FUNCTION__, __LINE__, websocket_cfg.uri); + + s_voicechat_ws_client_p = voicechat_websocket_client_init(&websocket_cfg); + if(NULL == s_voicechat_ws_client_p) + { + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: websocket client init fail\n", __FUNCTION__, __LINE__); + return; + } + + voicechat_websocket_register_events(s_voicechat_ws_client_p, mmi_voicechat_websocket_event_handler); + + esp_err_t err_no = voicechat_websocket_client_start(s_voicechat_ws_client_p); + if(ESP_OK != err_no) + { + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: websocket client start fail,%d\n", __FUNCTION__, __LINE__, err_no); + return; + } + else + { + + } + + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: client_p=%#X\n", __FUNCTION__, __LINE__, s_voicechat_ws_client_p); +} + +void mmi_voicechat_websocket_app_stop(void) +{ + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: client_p=%#X\n", __FUNCTION__, __LINE__, s_voicechat_ws_client_p); + + if(NULL != s_voicechat_ws_client_p) + { + voicechat_websocket_client_destroy(s_voicechat_ws_client_p); + s_voicechat_ws_client_p = NULL; + } + + VOICECHAT_WB_DEBUG_PRINTF("[@CHENG_DEBUG][%s][%d]: client_p=%#X\n", __FUNCTION__, __LINE__, s_voicechat_ws_client_p); +} + +#endif + diff --git a/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/src/mmi_voicechat_websocket_client.c b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/src/mmi_voicechat_websocket_client.c new file mode 100644 index 00000000..48199820 --- /dev/null +++ b/2.sdk/sdk/product/craneg_modem/pcac/wsclient/libwebsockets/src/mmi_voicechat_websocket_client.c @@ -0,0 +1,832 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// 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 + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "mmi_voicechat_websocket_client.h" +#include "web_esp_transport.h" +#include "web_esp_transport_tcp.h" +#include "web_esp_transport_ssl.h" +#include "web_esp_transport_ws.h" + +/* using uri parser */ +#include "web_http_parser.h" +#include "queue.h" +#include "esp_log.h" +#include "sockets.h" +#include "osa.h" + + +#ifdef __MMI_CUSTOM_VOICECHAT_SUPPORT__ + +static int task_run = 0; +static OSTaskRef voicechat_websocket_client_ref = NULL; +static void * voicechat_websocket_client_stack_ptr = NULL; + +#define websocket_version "asr_websocket_v1.10_20210926" +#define WEBSOCKET_TCP_DEFAULT_PORT (80) +#define WEBSOCKET_SSL_DEFAULT_PORT (443) +#define WEBSOCKET_BUFFER_SIZE_BYTE (80*1024) // (8*1024) +#define WEBSOCKET_RECONNECT_TIMEOUT_MS (5*60*1000) +#define WEBSOCKET_TASK_PRIORITY (90) +#define WEBSOCKET_TASK_STACK (8*1024) +#define WEBSOCKET_NETWORK_TIMEOUT_MS (10*1000) +#define WEBSOCKET_PING_TIMEOUT_MS (15*60*1000) +#define WEBSOCKET_EVENT_QUEUE_SIZE (1) + +#define ESP_WS_CLIENT_MEM_CHECK(a, action) if (!(a)) { \ + ESP_LOGE("%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ + action; \ + } +#define ESP_EVENT_DECLARE_BASE(id) extern esp_event_base_t id +#define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id + +static int voicechat_websocket_client_send_with_opcode(sim_esp_websocket_client_handle_t client, ws_transport_opcodes_t opcode, const char *data, int len, TickType_t timeout); +static void asr_ws_loop_run_task(void *pv); +extern OSMsgQRef asr_ws_msgQ_ref; +extern int esp_transport_ws_poll_connection_closed(wb_esp_transport_handle_t t, int timeout_ms); + +static UINT32 _tick_get_ms(void) +{ + return (5*OSAGetTicks()); //get ms + //return esp_timer_get_time()/1000; +} + +static int voicechat_websocket_client_dispatch_event(sim_esp_websocket_client_handle_t client, + sim_esp_websocket_event_id_t event, + const char *data, + int data_len) +{ + if (client->handler) { + if (NULL == data) { + client->handler(event, NULL); + } else { + sim_esp_websocket_event_data_t *event_data = NULL; + event_data = malloc(sizeof(sim_esp_websocket_event_data_t)); + if (NULL == event_data) { + ESP_LOGE("%s, event_data malloc failed", __FUNCTION__); + return -1; + } else { + memset(event_data, '\0', sizeof(sim_esp_websocket_event_data_t)); + event_data->data_ptr = malloc(data_len); + if (event_data->data_ptr) { + memset(event_data->data_ptr, 0, data_len); + memcpy(event_data->data_ptr, data, data_len); + } + } + + event_data->data_len = data_len; + event_data->op_code = client->last_opcode; + //shenxj+++ + event_data->payload_len = client->payload_len; + event_data->payload_offset = client->payload_offset; + //shenxj--- + + client->handler(event, event_data); + } + } + + return 0; +} + +static int voicechat_websocket_client_abort_connection(sim_esp_websocket_client_handle_t client) +{ + int ret = 0; + + wb_esp_transport_close(client->transport); + client->wait_timeout_ms = WEBSOCKET_RECONNECT_TIMEOUT_MS; + client->reconnect_tick_ms = _tick_get_ms(); + client->state = WEBSOCKET_STATE_WAIT_TIMEOUT; + ESP_LOGI("Reconnect after %d ms", client->wait_timeout_ms); + ret = voicechat_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_DISCONNECTED, NULL, 0); + ESP_LOGD("%s, client abort connection ret is %d", __FUNCTION__, ret); + return ret; +} + +static esp_err_t voicechat_websocket_client_set_config(sim_esp_websocket_client_handle_t client, const sim_esp_websocket_client_config_t *config) +{ + sim_websocket_config_storage_t *cfg = client->config; + cfg->task_prio = config->task_prio; + if (cfg->task_prio <= 0) { + cfg->task_prio = WEBSOCKET_TASK_PRIORITY; + } + + cfg->task_stack = config->task_stack; + if (cfg->task_stack == 0) { + cfg->task_stack = WEBSOCKET_TASK_STACK; + } + + if (config->host) { + cfg->p_host = strdup(config->host); + memcpy(cfg->host, cfg->p_host, strlen(config->host)); + ESP_WS_CLIENT_MEM_CHECK(cfg->host, return ESP_ERR_NO_MEM); + } + + if (config->port) { + cfg->port = config->port; + } + + if (config->username) { + //free(cfg->username); + cfg->username = strdup(config->username); + ESP_WS_CLIENT_MEM_CHECK(cfg->username, return ESP_ERR_NO_MEM); + } + + if (config->password) { + //free(cfg->password); + cfg->password = strdup(config->password); + ESP_WS_CLIENT_MEM_CHECK(cfg->password, return ESP_ERR_NO_MEM); + } + + if (config->uri) { + //free(cfg->uri); + cfg->uri = strdup(config->uri); + ESP_WS_CLIENT_MEM_CHECK(cfg->uri, return ESP_ERR_NO_MEM); + } + if (config->path) { + //free(cfg->path); + cfg->p_path = strdup(config->path); + memcpy(cfg->path, cfg->p_path, strlen(config->path)); + ESP_WS_CLIENT_MEM_CHECK(cfg->path, return ESP_ERR_NO_MEM); + } + if (config->subprotocol) { + //free(cfg->subprotocol); + cfg->subprotocol = strdup(config->subprotocol); + ESP_WS_CLIENT_MEM_CHECK(cfg->subprotocol, return ESP_ERR_NO_MEM); + } + + cfg->network_timeout_ms = WEBSOCKET_NETWORK_TIMEOUT_MS; + cfg->user_context = config->user_context; + cfg->auto_reconnect = true; + if (config->disable_auto_reconnect) { + cfg->auto_reconnect = false; + } + + + return ESP_OK; +} + +static esp_err_t voicechat_websocket_client_destroy_config(sim_esp_websocket_client_handle_t client) +{ + if (client == NULL) { + return ESP_ERR_INVALID_ARG; + } + sim_websocket_config_storage_t *cfg = client->config; + if (client->config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (NULL != cfg->p_host) { + free(cfg->p_host); + cfg->p_host = NULL; + } + if (NULL != cfg->uri) { + free(cfg->uri); + cfg->uri = NULL; + } + if (NULL != cfg->p_path) { + free(cfg->p_path); + cfg->p_path = NULL; + } + if (NULL != cfg->username) { + free(cfg->username); + cfg->username = NULL; + } + if (NULL != cfg->password) { + free(cfg->password); + cfg->password = NULL; + } + if (NULL != cfg->subprotocol) { + free(cfg->subprotocol); + cfg->subprotocol = NULL; + } + + memset(cfg, 0, sizeof(sim_websocket_config_storage_t)); + free(client->config); + client->config = NULL; + return ESP_OK; +} + +static void set_websocket_transport_optional_settings(sim_esp_websocket_client_handle_t client, wb_esp_transport_handle_t trans) +{ + if (trans && client->config->path) { + wb_esp_transport_ws_set_path(trans, client->config->path); + } + if (trans && client->config->subprotocol) { + wb_esp_transport_ws_set_subprotocol(trans, client->config->subprotocol); + } +} + +sim_esp_websocket_client_handle_t voicechat_websocket_client_init(const sim_esp_websocket_client_config_t *config) +{ + wb_esp_transport_handle_t tcp = NULL; + wb_esp_transport_handle_t ws = NULL; + wb_esp_transport_handle_t ssl = NULL; + wb_esp_transport_handle_t wss = NULL; + int buffer_size = 0; + OS_STATUS status; + + sim_esp_websocket_client_handle_t client = (sim_esp_websocket_client_handle_t)malloc(1*sizeof(struct sim_esp_websocket_client)); + ESP_WS_CLIENT_MEM_CHECK(client, return NULL); + memset(client, '\0', sizeof(struct sim_esp_websocket_client)); + client->state = WEBSOCKET_STATE_UNKNOW; + + status = OSAMutexCreate(&client->lock, OSA_FIFO); + if (OS_SUCCESS != status) { + ESP_LOGE("Failed to create client lock"); + } + + client->config = calloc(1, sizeof(sim_websocket_config_storage_t)); + ESP_WS_CLIENT_MEM_CHECK(client->config, goto _websocket_init_fail); + + client->transport_list = wb_esp_transport_list_init(); + ESP_WS_CLIENT_MEM_CHECK(client->transport_list, goto _websocket_init_fail); + + tcp = wb_esp_transport_tcp_init(); + ESP_WS_CLIENT_MEM_CHECK(tcp, goto _websocket_init_fail); + + wb_esp_transport_set_default_port(tcp, WEBSOCKET_TCP_DEFAULT_PORT); + wb_esp_transport_list_add(client->transport_list, tcp, "_tcp"); // need to save to transport list, for cleanup + + + ws = wb_esp_transport_ws_init(tcp); + ESP_WS_CLIENT_MEM_CHECK(ws, goto _websocket_init_fail); + + wb_esp_transport_set_default_port(ws, WEBSOCKET_TCP_DEFAULT_PORT); + wb_esp_transport_list_add(client->transport_list, ws, "ws"); + if (config->transport == WEBSOCKET_TRANSPORT_OVER_TCP) { + sprintf(client->config->scheme, "%s", "ws"); + ESP_WS_CLIENT_MEM_CHECK(client->config->scheme, goto _websocket_init_fail); + } + + ssl = wb_esp_transport_ssl_init(); + ESP_WS_CLIENT_MEM_CHECK(ssl, goto _websocket_init_fail); + + wb_esp_transport_set_default_port(ssl, WEBSOCKET_SSL_DEFAULT_PORT); + if (config->cert_pem) { + wb_esp_transport_ssl_set_cert_data(ssl, config->cert_pem, strlen(config->cert_pem)); + } + wb_esp_transport_list_add(client->transport_list, ssl, "_ssl"); // need to save to transport list, for cleanup + + wss = wb_esp_transport_ws_init(ssl); + ESP_WS_CLIENT_MEM_CHECK(wss, goto _websocket_init_fail); + + wb_esp_transport_set_default_port(wss, WEBSOCKET_SSL_DEFAULT_PORT); + + wb_esp_transport_list_add(client->transport_list, wss, "wss"); + if (config->transport == WEBSOCKET_TRANSPORT_OVER_SSL) { + sprintf(client->config->scheme, "%s", "wss"); + ESP_WS_CLIENT_MEM_CHECK(client->config->scheme, goto _websocket_init_fail); + } + + if (config->uri) { + if (voicechat_websocket_client_set_uri(client, config->uri) != ESP_OK) { + ESP_LOGE("Invalid uri"); + goto _websocket_init_fail; + } + } + + if (voicechat_websocket_client_set_config(client, config) != ESP_OK) { + ESP_LOGE("Failed to set the configuration"); + goto _websocket_init_fail; + } + + if (client->config->scheme == NULL) { + sprintf(client->config->scheme, "%s", "ws"); + ESP_WS_CLIENT_MEM_CHECK(client->config->scheme, goto _websocket_init_fail); + } + + set_websocket_transport_optional_settings(client, wb_esp_transport_list_get_transport(client->transport_list, "ws")); + set_websocket_transport_optional_settings(client, wb_esp_transport_list_get_transport(client->transport_list, "wss")); + + client->keepalive_tick_ms = _tick_get_ms(); + client->reconnect_tick_ms = _tick_get_ms(); + client->ping_tick_ms = _tick_get_ms(); + + buffer_size = config->buffer_size; + if (buffer_size <= 0) { + buffer_size = WEBSOCKET_BUFFER_SIZE_BYTE; + } + client->rx_buffer = malloc(buffer_size); + ESP_WS_CLIENT_MEM_CHECK(client->rx_buffer, { + goto _websocket_init_fail; + }); + client->tx_buffer = malloc(buffer_size); + ESP_WS_CLIENT_MEM_CHECK(client->tx_buffer, { + goto _websocket_init_fail; + }); + + client->buffer_size = buffer_size; + return client; + +_websocket_init_fail: + voicechat_websocket_client_destroy(client); + return NULL; +} + +esp_err_t voicechat_websocket_client_destroy(sim_esp_websocket_client_handle_t client) +{ + if (client == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (1 == task_run) { + voicechat_websocket_client_stop(client); + } + + OSAMutexDelete(client->lock); + + voicechat_websocket_client_destroy_config(client); + + wb_esp_transport_list_destroy(client->transport_list); + + if (NULL != client->tx_buffer) { + free(client->tx_buffer); + client->tx_buffer = NULL; + } + if (NULL != client->rx_buffer) { + free(client->rx_buffer); + client->rx_buffer = NULL; + } + if (NULL != client) { + free(client); + client = NULL; + } + + return ESP_OK; +} + +esp_err_t voicechat_websocket_client_set_uri(sim_esp_websocket_client_handle_t client, const char *uri) +{ + if (client == NULL || uri == NULL) { + return ESP_ERR_INVALID_ARG; + } + struct http_parser_url puri; + wb_http_parser_url_init(&puri); + int parser_status = wb_http_parser_parse_url(uri, strlen(uri), 0, &puri); + if (parser_status != 0) { + ESP_LOGE("Error parse uri = %s", uri); + return ESP_FAIL; + } + if (puri.field_data[UF_SCHEMA].len) { + //free(client->config->scheme); + sprintf(client->config->scheme, "%.*s", puri.field_data[UF_SCHEMA].len, uri + puri.field_data[UF_SCHEMA].off); + ESP_WS_CLIENT_MEM_CHECK(client->config->scheme, return ESP_ERR_NO_MEM); + } + + if (puri.field_data[UF_HOST].len) { + //free(client->config->host); + sprintf(client->config->host, "%.*s", puri.field_data[UF_HOST].len, uri + puri.field_data[UF_HOST].off); + ESP_WS_CLIENT_MEM_CHECK(client->config->host, return ESP_ERR_NO_MEM); + } + + + if (puri.field_data[UF_PATH].len || puri.field_data[UF_QUERY].len) { + //free(client->config->path); + if (puri.field_data[UF_QUERY].len == 0) { + sprintf(client->config->path, "%.*s", puri.field_data[UF_PATH].len, uri + puri.field_data[UF_PATH].off); + } else if (puri.field_data[UF_PATH].len == 0) { + sprintf(client->config->path, "/?%.*s", puri.field_data[UF_QUERY].len, uri + puri.field_data[UF_QUERY].off); + } else { + sprintf(client->config->path, "%.*s?%.*s", puri.field_data[UF_PATH].len, uri + puri.field_data[UF_PATH].off, + puri.field_data[UF_QUERY].len, uri + puri.field_data[UF_QUERY].off); + } + ESP_WS_CLIENT_MEM_CHECK(client->config->path, return ESP_ERR_NO_MEM); + } + if (puri.field_data[UF_PORT].off) { + client->config->port = strtol((const char*)(uri + puri.field_data[UF_PORT].off), NULL, 10); + } + + if (puri.field_data[UF_USERINFO].len) { + char user_info[1024]; + memset(user_info, '\0', 1024); + sprintf(user_info, "%.*s", puri.field_data[UF_USERINFO].len, uri + puri.field_data[UF_USERINFO].off); + if (user_info) { + char *pass = strchr(user_info, ':'); + if (pass) { + pass[0] = 0; //terminal username + pass ++; + //free(client->config->password); + client->config->password = strdup(pass); + ESP_WS_CLIENT_MEM_CHECK(client->config->password, return ESP_ERR_NO_MEM); + } + //free(client->config->username); + client->config->username = strdup(user_info); + ESP_WS_CLIENT_MEM_CHECK(client->config->username, return ESP_ERR_NO_MEM); + //free(user_info); + } else { + return ESP_ERR_NO_MEM; + } + } + return ESP_OK; +} + +static esp_err_t voicechat_websocket_client_recv(sim_esp_websocket_client_handle_t client) +{ + int rlen; + client->payload_offset = 0; + memset(client->rx_buffer, 0, client->buffer_size); + do { + rlen = wb_esp_transport_read(client->transport, client->rx_buffer, client->buffer_size, client->config->network_timeout_ms); + if (rlen <= 0) { + ESP_LOGE("Error read data"); + voicechat_websocket_client_abort_connection(client); + return ESP_FAIL; + } + client->payload_len = wb_esp_transport_ws_get_read_payload_len(client->transport); + client->last_opcode = wb_esp_transport_ws_get_read_opcode(client->transport); + + voicechat_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_DATA, client->rx_buffer, rlen); + + client->payload_offset += rlen; + } while (client->payload_offset < client->payload_len); + + // if a PING message received -> send out the PONG, this will not work for PING messages with payload longer than buffer len + if (client->last_opcode == WS_TRANSPORT_OPCODES_PING) { + const char *data = (client->payload_len == 0) ? NULL : client->rx_buffer; + wb_esp_transport_ws_send_raw(client->transport, WS_TRANSPORT_OPCODES_PONG, data, client->payload_len, + client->config->network_timeout_ms); + } else if (client->last_opcode == WS_TRANSPORT_OPCODES_CLOSE) { + ESP_LOGD("Received close frame"); + client->state = WEBSOCKET_STATE_CLOSING; + } + + return ESP_OK; +} + +static void voicechat_websocket_client_task(void *pv) +{ + OSA_STATUS status; + int ret = 0; + const int lock_timeout = portMAX_DELAY; + sim_esp_websocket_client_handle_t client = (sim_esp_websocket_client_handle_t) pv; + task_run = 1; + + //get transport by scheme + client->transport = wb_esp_transport_list_get_transport(client->transport_list, client->config->scheme); + + if (client->transport == NULL) { + ESP_LOGE("There are no transports valid, stop websocket client"); + task_run = 0; + } + //default port + if (client->config->port == 0) { + client->config->port = wb_esp_transport_get_default_port(client->transport); + } + + client->state = WEBSOCKET_STATE_INIT; + int read_select = 0; + while (1) { + if (0 == task_run) { + ESP_LOGE("%s: task_run=0 and task exit", __FUNCTION__); + break; + } + + //ESP_LOGD("%s, client state is %d, client->run is %d", + // __FUNCTION__, (int)client->state, task_run); + + status = OSAMutexLock(client->lock, OSA_SUSPEND); + if (status != OS_SUCCESS) { + ESP_LOGE("%s: get lock failed and task exit", __FUNCTION__); + break; + } + switch ((int)client->state) { + case WEBSOCKET_STATE_INIT: + if (client->transport == NULL) { + ESP_LOGE("There are no transport"); + task_run = 0; + break; + } + + if (wb_esp_transport_connect(client->transport, + client->config->host, + client->config->port, + client->config->network_timeout_ms) < 0) { + ESP_LOGE("Error transport connect"); + ret = voicechat_websocket_client_abort_connection(client); + ESP_LOGD("%s, client abort connection ret is %d", __FUNCTION__, ret); + break; + } + ESP_LOGD("Transport connected to %s://%s:%d", client->config->scheme, client->config->host, client->config->port); + + client->state = WEBSOCKET_STATE_CONNECTED; + voicechat_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_CONNECTED, NULL, 0); + + break; + case WEBSOCKET_STATE_CONNECTED: + if (_tick_get_ms() - client->ping_tick_ms > WEBSOCKET_PING_TIMEOUT_MS) { + client->ping_tick_ms = _tick_get_ms(); + ESP_LOGD("Sending PING..."); + wb_esp_transport_ws_send_raw(client->transport, WS_TRANSPORT_OPCODES_PING, NULL, 0, client->config->network_timeout_ms); + } + + if (read_select == 0) { + //ESP_LOGV("Read poll timeout: skipping esp_transport_read()..."); + break; + } + client->ping_tick_ms = _tick_get_ms(); + + if (voicechat_websocket_client_recv(client) == ESP_FAIL) { + ESP_LOGE("Error receive data"); + voicechat_websocket_client_abort_connection(client); + break; + } + break; + case WEBSOCKET_STATE_WAIT_TIMEOUT: + if (!client->config->auto_reconnect) { + task_run = 0; + break; + } + if (_tick_get_ms() - client->reconnect_tick_ms > client->wait_timeout_ms) { + client->state = WEBSOCKET_STATE_INIT; + client->reconnect_tick_ms = _tick_get_ms(); + ESP_LOGD("Reconnecting..."); + } else { + client->state = WEBSOCKET_STATE_WAIT_TIMEOUT; + ESP_LOGD("Waiting connect..."); + } + break; + case WEBSOCKET_STATE_CLOSING: + // if closing not initiated by the client echo the close message back + ESP_LOGD("Closing initiated by the server, sending close frame"); + wb_esp_transport_ws_send_raw(client->transport, WS_TRANSPORT_OPCODES_CLOSE | WS_TRANSPORT_OPCODES_FIN, NULL, 0, client->config->network_timeout_ms); + break; + + default: + ESP_LOGD("Client run iteration in a default state: %d", client->state); + break; + } + OSAMutexUnlock(client->lock); + + if (WEBSOCKET_STATE_CONNECTED == client->state) { + read_select = wb_esp_transport_poll_read(client->transport, 1000); //Poll every 1000ms + if (read_select < 0) { + ESP_LOGE("Network error: esp_transport_poll_read() returned %d, errno=%d", read_select, errno); + voicechat_websocket_client_abort_connection(client); + } + } else if (WEBSOCKET_STATE_WAIT_TIMEOUT == client->state) { + // waiting for reconnecting... + OSATaskSleep(client->wait_timeout_ms / 2 / sim_portTICK_RATE_MS); + } else if (WEBSOCKET_STATE_CLOSING == client->state) { + ESP_LOGD(" Waiting for TCP connection to be closed by the server"); + ret = esp_transport_ws_poll_connection_closed(client->transport, 1000); + if (ret == 0) { + // still waiting + break; + } + if (ret < 0) { + ESP_LOGW("Connection terminated while waiting for clean TCP close"); + } + task_run = 0; + client->state = WEBSOCKET_STATE_UNKNOW; + voicechat_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_CLOSED, NULL, 0); + break; + } + } + + wb_esp_transport_close(client->transport); + client->state = WEBSOCKET_STATE_UNKNOW; + ESP_LOGD("%s task exit!task_run=%d, client state=%d", + __FUNCTION__, task_run, client->state); + return; +} + +esp_err_t voicechat_websocket_client_start(sim_esp_websocket_client_handle_t client) +{ + OS_STATUS status = OS_SUCCESS; + + if (client == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (client->state > WEBSOCKET_STATE_INIT) { + ESP_LOGE("The client has started and client state is %d", client->state); + return ESP_FAIL; + } + + if (NULL == voicechat_websocket_client_ref) { + if (NULL == voicechat_websocket_client_stack_ptr) { + voicechat_websocket_client_stack_ptr = malloc(8*1024); + if (NULL == voicechat_websocket_client_stack_ptr) { + ESP_LOGE("websocket task stack malloc failed."); + return ESP_ERR_NO_MEM; + } + } + status = OSATaskCreate(&voicechat_websocket_client_ref, + voicechat_websocket_client_stack_ptr, + 8*1024, + 90, + "voicechat_ws_task", + voicechat_websocket_client_task, + (void *)client); + if (OS_SUCCESS != status) { + if (voicechat_websocket_client_stack_ptr) { + free(voicechat_websocket_client_stack_ptr); + voicechat_websocket_client_stack_ptr = NULL; + } + ESP_LOGE("Error create websocket task"); + } + } else { + ESP_LOGD("websocket task is exist!"); + } + + ESP_LOGD("websocket_version: %s.", websocket_version); + ESP_LOGD("create ws task SUCCESS!"); + return ESP_OK; +} + +esp_err_t voicechat_websocket_client_stop(sim_esp_websocket_client_handle_t client) +{ + if (client == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (0 == task_run) { + ESP_LOGW("Client was not started"); + return ESP_FAIL; + } + task_run = 0; + client->state = WEBSOCKET_STATE_UNKNOW; + //delete task + if(voicechat_websocket_client_ref == NULL) { + ESP_LOGD("websocket task is not exist!"); + return ESP_FAIL; + } + ESP_LOGD("task deleting..."); +#if 1 //liangrf @ fixed Bug #50522 (release select_cb) + lwip_trigger_process("select", voicechat_websocket_client_ref); +#endif + OSA_STATUS delete_status = OSATaskDelete(voicechat_websocket_client_ref); + ESP_LOGD("task deleted, deleteTaskRet is %d...", delete_status); + if(voicechat_websocket_client_stack_ptr) { + free(voicechat_websocket_client_stack_ptr); + voicechat_websocket_client_stack_ptr = NULL; + } + voicechat_websocket_client_ref = NULL; + //delete task + + ESP_LOGD("%s, client state is %d, task_run is %d", + __FUNCTION__, (int)client->state, task_run); + return ESP_OK; +} + +static int voicechat_websocket_client_send_close(sim_esp_websocket_client_handle_t client, int code, const char *additional_data, int total_len, TickType_t timeout) +{ + char *close_status_data = NULL; + // RFC6455#section-5.5.1: The Close frame MAY contain a body (indicated by total_len >= 2) + if (total_len >= 2) { + close_status_data = calloc(1, total_len); + ESP_WS_CLIENT_MEM_CHECK(close_status_data, return -1); + // RFC6455#section-5.5.1: The first two bytes of the body MUST be a 2-byte representing a status + uint16_t *code_network_order = (uint16_t *) close_status_data; + *code_network_order = htons(code); + memcpy(close_status_data + 2, additional_data, total_len - 2); + } + int ret = voicechat_websocket_client_send_with_opcode(client, WS_TRANSPORT_OPCODES_CLOSE, close_status_data, total_len, timeout); + if (NULL != close_status_data) { + free(close_status_data); + close_status_data = NULL; + } + return ret; +} + + +static int voicechat_websocket_client_close_with_optional_body(sim_esp_websocket_client_handle_t client, bool send_body, int code, const char *data, int len, TickType_t timeout) +{ + int ret = 0; + + if (client == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (0 == task_run) { + ESP_LOGW("Client was not started"); + return ESP_FAIL; + } + + if (send_body) { + ret = voicechat_websocket_client_send_close(client, code, data, len + 2, portMAX_DELAY); // len + 2 -> always sending the code + } else { + ret = voicechat_websocket_client_send_close(client, 0, NULL, 0, portMAX_DELAY); // only opcode frame + } + + // If could not close gracefully within timeout, stop the client and disconnect + //task_run = 0; + //client->state = WEBSOCKET_STATE_UNKNOW; + if (ret >= 0) { + return ESP_OK; + } else { + ESP_LOGW("Client send close failed"); + return ESP_FAIL; + } +} + +int voicechat_websocket_client_close_with_code(sim_esp_websocket_client_handle_t client, int code, const char *data, int len, TickType_t timeout) +{ + return voicechat_websocket_client_close_with_optional_body(client, true, code, data, len, timeout); +} + +int voicechat_websocket_client_close(sim_esp_websocket_client_handle_t client, TickType_t timeout) +{ + return voicechat_websocket_client_close_with_optional_body(client, false, 0, NULL, 0, timeout); +} + +int voicechat_websocket_client_send_text(sim_esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout) +{ + return voicechat_websocket_client_send_with_opcode(client, WS_TRANSPORT_OPCODES_TEXT, data, len, timeout); +} + +int voicechat_websocket_client_send(sim_esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout) +{ + return voicechat_websocket_client_send_with_opcode(client, WS_TRANSPORT_OPCODES_BINARY, data, len, timeout); +} + +int voicechat_websocket_client_send_bin(sim_esp_websocket_client_handle_t client, const char *data, int len, TickType_t timeout) +{ + return voicechat_websocket_client_send_with_opcode(client, WS_TRANSPORT_OPCODES_BINARY, data, len, timeout); +} + +static int voicechat_websocket_client_send_with_opcode(sim_esp_websocket_client_handle_t client, ws_transport_opcodes_t opcode, const char *data, int len, TickType_t timeout) +{ + int need_write = len; + int wlen = 0, widx = 0; + int ret = ESP_FAIL; + UINT32 current_opcode = opcode; + OSA_STATUS status; + + if (client == NULL || len < 0 || + (opcode != WS_TRANSPORT_OPCODES_CLOSE && (data == NULL || len <= 0))) { + ESP_LOGE("Invalid arguments"); + return ESP_FAIL; + } + + status = OSAMutexLock(client->lock, timeout); + if (status != OS_SUCCESS) { + ESP_LOGE("%s: get lock failed and return error", __FUNCTION__); + return ESP_FAIL; + } + if (!voicechat_websocket_client_is_connected(client)) { + ESP_LOGE("Websocket client is not connected"); + goto unlock_and_return; + } + + if (client->transport == NULL) { + ESP_LOGE("Invalid transport"); + goto unlock_and_return; + } + + while (widx < len || current_opcode) { // allow for sending "current_opcode" only message with len==0 + if (need_write > client->buffer_size) { + need_write = client->buffer_size; + } else { + current_opcode |= WS_TRANSPORT_OPCODES_FIN; + } + memcpy(client->tx_buffer, data + widx, need_write); + // send with ws specific way and specific opcode + wlen = wb_esp_transport_ws_send_raw(client->transport, current_opcode, (char *)client->tx_buffer, need_write, + (timeout==portMAX_DELAY)? -1 : timeout * sim_portTICK_PERIOD_MS); + if (wlen < 0 || (wlen == 0 && need_write != 0)) { + ret = wlen; + ESP_LOGE("Network error: esp_transport_write() returned %d, errno=%d", ret, errno); + voicechat_websocket_client_abort_connection(client); + goto unlock_and_return; + } + current_opcode = 0; + widx += wlen; + need_write = len - widx; + } + + ret = widx; +unlock_and_return: + OSAMutexUnlock(client->lock); + return ret; +} + +bool voicechat_websocket_client_is_connected(sim_esp_websocket_client_handle_t client) +{ + if (client == NULL) { + return false; + } + return client->state == WEBSOCKET_STATE_CONNECTED; +} + +esp_err_t voicechat_websocket_register_events(sim_esp_websocket_client_handle_t client, + sim_esp_event_handler_t event_handler) +{ + if (client == NULL) { + return -1; + } + ESP_LOGD("client handler register success!!"); + client->handler = event_handler; + return 0; +} + +#endif +