From f5b0a07f1b18596a4ff028ccae4107e5ea9219bb Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Fri, 29 Aug 2025 14:27:34 +0800 Subject: [PATCH] =?utf8?q?AI=E5=85=A8=E5=AE=B6=E6=A1=B6=E4=BB=A3=E7=A0=81?= =?utf8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../wearable/fd230/nativeapp/CMakeLists.txt | 1 + .../aivoice/include/AiVoiceConnectingView.h | 1 - .../nativeui/aivoice/include/AiVoiceModel.h | 64 +- .../nativeui/aivoice/include/AiVoiceModelC.h | 21 + .../aivoice/include/AiVoicePresenter.h | 16 +- .../aivoice/include/AiVoiceSelectView.h | 31 + .../nativeui/aivoice/include/AiVoiceView.h | 28 +- .../aivoice/include/AiVoiceVolumeView.h | 23 + .../aivoice/include/Aivoice4gServiceConView.h | 26 + .../include/AivoiceChatContentListItemView.h | 1 + .../aivoice/include/AivoiceListeningView.h | 2 +- .../include/AivoiceReturnResultTextView.h | 1 + .../aivoice/include/AivoiceThinkingView.h | 2 +- .../aivoice/src/AiVoiceConnectingView.cpp | 108 +- .../nativeui/aivoice/src/AiVoiceModel.cpp | 1225 ++++++++++++++--- .../nativeui/aivoice/src/AiVoicePresenter.cpp | 563 ++++++-- .../aivoice/src/AiVoiceSelectView.cpp | 175 +++ .../nativeui/aivoice/src/AiVoiceView.cpp | 474 +++++-- .../aivoice/src/AiVoiceVolumeView.cpp | 77 ++ .../aivoice/src/Aivoice4gServiceConView.cpp | 134 ++ .../src/AivoiceChatContentListItemView.cpp | 34 +- .../aivoice/src/AivoiceListeningView.cpp | 102 +- .../src/AivoiceReturnResultTextView.cpp | 11 +- .../aivoice/src/AivoiceThinkingView.cpp | 120 +- code/sdk/zhihui/ai/include/cat1_ws.h | 5 + 25 files changed, 2696 insertions(+), 549 deletions(-) create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp diff --git a/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt b/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt index 55059fcb8..76dac27e4 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt +++ b/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt @@ -75,6 +75,7 @@ set(PRIVATE_HEADER ${ROOT_DIR}/zhihui/4g/cat1Service ${ROOT_DIR}/zhihui/4g/cat1Service/include ${ROOT_DIR}/zhihui/4g/cat1Service/Service + ${ROOT_DIR}/zhihui/ai/include/ ) diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceConnectingView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceConnectingView.h index 4f69a4e44..2042f7f7b 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceConnectingView.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceConnectingView.h @@ -80,7 +80,6 @@ namespace OHOS UIButton *cancelButton{nullptr}; UIImageAnimatorView *connectingAnimatorView{nullptr}; ImageAnimatorInfo connectingImageInfo[AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES]; - const ImageInfo **connectingPathsArray{nullptr}; }; } diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModel.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModel.h index f45155f05..529c51896 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModel.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModel.h @@ -18,11 +18,25 @@ #define AIAUDIO_TYPE_SBC 1 #define AIAUDIO_TYPE_MSBC 2 +#define AI_VOICE_ENABLE 0 + // 设置当前使用的音频类型,0 表示 PCM,1 表示 SBC,2 表示 MSBC #define CURRENT_AIAUDIO_TYPE AIAUDIO_TYPE_SBC +#if defined(SUPPORT_CHINA_MOBILE_DMP) || defined(SUPPORT_CHINA_MOBILE_AI_REGULATION) + #define AI_VOICE_FD230 // 九天版本 +#elif defined(BOARD_N9) + #define AI_VOICE_N9 //N9 星辰Ai +#else + #define AI_VOICE_FD230 +#endif + + namespace OHOS { +#define AI_SELECT_DEFAULT -1 +#define AI_SELECT_4G 1 +#define AI_SELECT_BT 0 class AiVoiceModel { @@ -48,8 +62,6 @@ namespace OHOS void DeleteLocalOpenAIAPIKeys(); bool GetAPPBluetoothIsConnect(void); bool GetMobileDataIsOpen(void); - bool GetAiVoiceConnectStatus(void); - void SetAiVoiceConnectStatus(bool state); void QuerySelectedAiModelIsConnect(); void CancelCurAIChat(void); int GetAIResponseType(void); @@ -64,6 +76,7 @@ namespace OHOS bool AddAiAnswerToChatItems(); bool AddChatContentToItemArray(const ChatContentItem &item); uint8_t GetChatContentListCount(void); + void SetChatContentListCount(uint8_t count); // 更新和清空问题及回答 bool RemoveLastTwoItemsOrClear(); @@ -78,9 +91,8 @@ namespace OHOS void SetAiAnswerStrStr(std::string str); void SetAiAnswerStrStr(std::string str,uint8_t type); uint8_t GetCurUsingAiModelType(void); + uint8_t GetCurUsing4GAiModelType(void); - // 文件检查和AI状态管理 - void CheckFileAndSendAIIsReady(); //发送AI已经就绪(继续对话时候使用) void sendAIIsReady(); @@ -106,6 +118,18 @@ namespace OHOS void start_ai_isready_timer(uint32_t interval = 1000); void stop_ai_isready_timer(void); + void start_ai4g_connect_timer(uint32_t interval = 1000); + void stop_ai4g_connect_timer(void); + + void start_ai4g_tts_play_timer(uint32_t interval = 600); + void stop_ai4g_tts_play_timer(void); + + void start_update_ai_answer_timer(uint32_t interval = 300); + void stop_update_ai_answer_timer(void); + + void start_uapi_stop_tts_timer(uint32_t interval = 2000); + void stop_uapi_stop_tts_timer(void); + void SetSelectAiModel(int index); int GetSelectAiModel(void); int GetAiModelTextId(void); @@ -118,6 +142,29 @@ namespace OHOS void SetIsLimitDisplayed(bool value); bool GetIsLimitDisplayed(void); + void SetAI_4G_state(bool state); + bool GetAI_4G_state(void); + void SetAI_BT_state(bool state); + bool GetAI_BT_state(void); + void SetInit_4gai_task(bool state); + bool GetInit_4gai_task(void); + void SetSelect4gorbt(int state); + int GetSelect4gorbt(void); + + void cancel_tts_play(void); + + void ProcessTextByPunctuation(); + std::string GetAccumulatedText(void); + void sendSegment(const std::string &text, size_t pos); + + bool is_need_to_jump_result_view(void); + + bool getentryTextViewState(void); + + bool get_is_first_receive(); + void set_is_first_receive(bool); + void delete_start_line_break_str(std::string &str); + private: AiVoiceModel(); ~AiVoiceModel(); @@ -134,6 +181,7 @@ namespace OHOS #endif std::string userQuestionStr; // 用户提出的问题 std::string aiAnswerStr; // AI回答的问题 + std::string accumulatedText; // tts播放文本 uint8_t ChatContentListCount{0}; // 列表数量 static const uint16_t MaxChatContentListCount = 2; // 对话列表最大数量 ChatContentItem chatTtems[MaxChatContentListCount] = {0, "", false}; // 对话项数组 @@ -145,6 +193,14 @@ namespace OHOS int16_t curView{0}; bool isClickable{false}; bool isLimitDisplayed{false};//AI答案是否显示到极限了 + + bool AI_4G_state{false}; //4g网络状态 + bool AI_BT_state{false}; //蓝牙连接状态 + bool init_4gai_task{false}; //4g服务器连接状态 + uint8_t select4gorbt{-1}; //0:4g 1:蓝牙 -1:未连接 + + bool isFirstReceive{true}; //静态变量标记是否是首次接收 + bool hasTtsStartSucceeded{false}; // uapi_start_tts 成功后置位,仅允许发送一次 }; } diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h new file mode 100644 index 000000000..c74b0bebe --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h @@ -0,0 +1,21 @@ +#ifndef AI_VOICE_MODELC_H +#define AI_VOICE_MODELC_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" +{ +#endif +#endif +#include + + uint8_t getselect4gorbtai(void); + uint8_t get_clear_queue_stream(void); + void set_clear_queue_stream(uint8_t); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoicePresenter.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoicePresenter.h index d432da20d..f35192776 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoicePresenter.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoicePresenter.h @@ -13,6 +13,7 @@ #include "View.h" #include "ui_resource_string.h" #include "components/ui_time_picker.h" +#include "components/ui_slider.h" #include "ModelListenerSample.h" namespace OHOS { @@ -23,8 +24,9 @@ namespace OHOS public UIView::OnDragListener, public RootView::OnKeyActListener, public UIPicker::SelectedListener, - public UIView::OnTouchListener, - public ModelListenerSample + public UIView::OnRotateListener, + public UIView::OnTouchListener + // public ModelListenerSample { public: typedef enum : uint8_t @@ -33,7 +35,7 @@ namespace OHOS AIMODES_KIMI, /*KIMI*/ AIMODES_DOUBAO, /*豆包*/ AIMODES_TONGYI_QIANWEN, /*通义千问->DeepSeek*/ - AIMODES_IFLYTEK_SPARK, /*讯飞星火->lingxi*/ + AIMODES_IFLYTEK_SPARK, /*讯飞星火*/ AIMODES_CHATGPT, /*chatgpt*/ AIMODES_MAX_NUM, } aimodels; @@ -42,10 +44,8 @@ namespace OHOS static AiVoicePresenter *GetInstance(); void OnStart() override; - void OnResume() override; - void OnPause() override; void OnStop() override; - void Notify() override; + // void Notify() override; void calculateChatContentItemViewHeight(std::string text, bool flag); bool JumpToReturnResultTextView(void); @@ -55,6 +55,8 @@ namespace OHOS void FunctionKeyOnClickToChangeAIModel(void); void DragLeftToRightChangeAIModel(void); void DragRightToLetfChangeAIModel(void); + void ChangeVolume(UIView &view, const RotateEvent &event); + void JumpThinkingView(void); private: bool OnClick(UIView &view, const ClickEvent &event) override; @@ -64,6 +66,8 @@ namespace OHOS bool OnDragEnd(UIView &view, const DragEvent &event) override; bool OnKeyAct(UIView &view, const KeyEvent &event) override; // 增加按键事件 void OnPickerStoped(UIPicker &picker) override; + bool OnRotate(UIView& view, const RotateEvent& event); + bool OnRotateEnd(UIView& view, const RotateEvent& event); AiVoiceModel *model; bool X_DRAG_FLAG{false}; diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h new file mode 100644 index 000000000..a920a21cb --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h @@ -0,0 +1,31 @@ +#ifndef AIVOICESELECTVIEW_H +#define AIVOICESELECTVIEW_H +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_button.h" + +namespace OHOS +{ + static constexpr const char *AIVOICE_SELECT_VIEW_BUTTON4G_VIEW_ID = "aivoice_select_view_button4g_view_id"; // 选择界面4G连接按钮 + static constexpr const char *AIVOICE_SELECT_VIEW_BUTTONBT_VIEW_ID = "aivoice_select_view_buttonbt_view_id"; // 选择界面蓝牙连接按钮 + + class AiVoiceSelectView + { + public: + AiVoiceSelectView(); + ~AiVoiceSelectView(); + static AiVoiceSelectView *GetInstance(void); + UIScrollView *CreateAiVoiceSelectView(void); + + private: + void ClearAll(void); + UILabelExt *title{nullptr}; + UIScrollView *scrollView{nullptr}; + UILabelExt *label4g{nullptr}; + UILabelExt *labelbt{nullptr}; + UIButton *button4g{nullptr}; + UIButton *buttonbt{nullptr}; + }; +} + +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceView.h index fc65f5595..48c5cb6b1 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceView.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceView.h @@ -15,6 +15,7 @@ #include "components/ui_scroll_view.h" #include "components/ui_image_view.h" #include "components/ui_picker.h" +#include "components/ui_slider.h" #include "aivoice/include/AiVoiceBluetoothFailedStartView.h" #include "aivoice/include/AivoiceMobileDataFailedStartView.h" #include "aivoice/include/AivoiceConnectTimeoutView.h" @@ -25,6 +26,9 @@ #include "aivoice/include/apikeys/NotSetApiKeysView.h" #include "aivoice/include/apikeys/ApiKeysDeleteView.h" #include "aivoice/include/AiVoiceConnectingView.h" +#include "aivoice/include/AiVoiceSelectView.h" +#include "aivoice/include/Aivoice4gServiceConView.h" +#include "aivoice/include/AiVoiceVolumeView.h" #include "ui_resource_string.h" #include "iostream" #include "string" @@ -39,7 +43,7 @@ namespace OHOS static constexpr const char *AIMODEL_TONGYI_QIANWEN_PATH = "/user/res/AIVoice/aimodels/aimodes_tongyi_qianwen.bin"; /*通义千问*/ static constexpr const char *AIMODEL_IFLYTEK_SPARK_PATH = "/user/res/AIVoice/aimodels/aimodes_iflytek_spark.bin"; /*讯飞星火*/ static constexpr const char *AIMODEL_DEEPSEEK_PATH = "/user/res/AIVoice/aimodels/aimodes_deepseek.bin"; /*deepseek*/ - static constexpr const char *AIMODEL_LINGXI_PATH = "/user/res/AIVoice/aimodels/aimodels_lingxi.bin"; /*lingxi*/ + static constexpr const char *AIMODEL_LINGXI_PATH = "/user/res/AIVoice/aimodels/aimodels_lingxi.bin"; /*jiutian*/ /*组件ID*/ static constexpr const char *AIVOICE_START_CHAT_BUTTON_VIEW_ID = "aivoice_start_chat_button_view_id"; // 开始对话 @@ -61,6 +65,9 @@ namespace OHOS AIVOICE_NOTSETAPIKEYS, // API Keys notset界面 AIVOICE_APIKEYS_DELETE, // API Keys 删除界面 AIVOICE_AIMODE_CONNECTING, // AI Mode正在连接视图 + AIVOICE_SELECT_VIEW, // AI选择界面 + AIVOICE_4GSERVICECON_VIEW, // AI4G连接中界面 + AIVOICE_VOLUME_VIEW, // AI音量界面 MAX_AIVOICE_VIEWID, } AIVOICEVIEWID; @@ -70,9 +77,9 @@ namespace OHOS {STR_AIMODELS_DOUBAO, AIMODEL_DOUBAO_PATH}, // {STR_TONGYI_QIANWEN, AIMODEL_TONGYI_QIANWEN_PATH}, {STR_DEEPSEEK, AIMODEL_DEEPSEEK_PATH}, - // {STR_IFLYTEK_SPARK, AIMODEL_IFLYTEK_SPARK_PATH}, - {STR_AIMODES_LINGXI, AIMODEL_LINGXI_PATH}, + {STR_IFLYTEK_SPARK, AIMODEL_IFLYTEK_SPARK_PATH}, {STR_AIMODES_CHATGPT, AIMODEL_CHATGPT_ON_PATH}, + {STR_JIUTIAN, AIMODEL_LINGXI_PATH}, }; class AiVoicePresenter; @@ -129,6 +136,9 @@ namespace OHOS bool ChangeAiVoicNotSetApiKeysView(int16_t thisView); bool ChangeAiVoicApiKeysDeleteView(int16_t thisView); bool ChangeAiVoicConnectingView(int16_t thisView); + bool ChangeAiVoicSelectView(int16_t thisView); + bool ChangeAiVoic4gServiceConView(int16_t thisView); + bool ChangeAiVoicVolumeView(int16_t thisView); void SetAiVoiceViewAllComponentsVisibilityStatus(); void ChangeAiModelAndUpdateComponentsStatus(void); @@ -147,6 +157,9 @@ namespace OHOS NotSetApiKeysView *p_NotSetApiKeysView{nullptr}; ApiKeysDeleteView *p_ApiKeysDeleteView{nullptr}; AiVoiceConnectingView *p_AiVoiceConnectingView{nullptr}; + AiVoiceSelectView *p_AiVoiceSelectView{nullptr}; + AiVoice4gServiceConView *p_Aivoice4gServiceConView{nullptr}; + AiVoiceVolumeView *p_AiVoiceVolumeView{nullptr}; private: UILabelExt *AiVoiceViewLabelInit(LabelConfig &labelconfig); @@ -157,9 +170,12 @@ namespace OHOS bool CreateAiVoiceViewButton(void); bool CreateAiVoiceViewPicker(void); bool CreateAiVoiceScrollView(void); - void CreateAiVoiceView(void); + bool CreateAiVoiceVoiceView(void); + UIScrollView *CreateAiVoiceView(void); + void ClearAllAiVoiceScrollView(void); void ClearAll(void); void SetComponentVisibility(UIView *component, bool isVisible); + UIScrollView *scrollView{nullptr}; UILabelExt *title{nullptr}; /*标题*/ UILabelExt *startChatLabel{nullptr}; /*开始对话标签,暂时不用*/ UIButton *startChatButton{nullptr}; /*开始对话按钮*/ @@ -172,7 +188,9 @@ namespace OHOS UIButton *apiKeysButton{nullptr}; /*API Keys按钮,,暂时不用*/ UIPicker *aiModelPicker{nullptr}; /*ai模型选择器*/ UIScrollView *AiVoiceScrollView[MAX_AIVOICE_VIEWID]{nullptr}; - bool viewInitStatus{false}; + /* ----------------------------------- 九天 ----------------------------------- */ + UISlider *VolumeProcess{nullptr}; + /* -------------------------------------------------------------------------- */ }; } #endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h new file mode 100644 index 000000000..b52aa2ab7 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h @@ -0,0 +1,23 @@ +#ifndef AIVOICEVOLUMEVIEW_H +#define AIVOICEVOLUMEVIEW_H + +#include "components/ui_scroll_view.h" +#include "soundandvibration/include/SoundAndVibrationVolumeSettingView.h" +namespace OHOS +{ + class AiVoiceVolumeView + { + public: + AiVoiceVolumeView(); + ~AiVoiceVolumeView(); + static AiVoiceVolumeView *GetInstance(void); + UIScrollView *CreateAiVoiceVolumeView(void); + void SetRequestFocus(); + + private: + void ClearAll(); + UIScrollView *SystemVolumeScrollView{nullptr}; + SoundAndVibrationVolumeSettingView *p_SoundAndVibrationVolumeSettingView{nullptr}; + }; +} +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h new file mode 100644 index 000000000..495e68a6b --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h @@ -0,0 +1,26 @@ +#ifndef AIVOICE4GSERVICECONVIEW_H +#define AIVOICE4GSERVICECONVIEW_H +#include "components/ui_scroll_view.h" +#include "components/ui_label_ext.h" +#include "components/ui_button.h" +#include "components/ui_image_animator.h" + +namespace OHOS +{ + class AiVoice4gServiceConView + { + public: + AiVoice4gServiceConView(); + ~AiVoice4gServiceConView(); + static AiVoice4gServiceConView *GetInstance(void); + UIScrollView *CreateAiVoice4gServiceConView(void); + + private: + void ClearAll(void); + UIScrollView *scrollView{nullptr}; + UILabelExt *label{nullptr}; + UIImageAnimatorView *AI4GImageAni{nullptr}; + ImageAnimatorInfo AI4GsearchImageInfo[8]; + }; +} +#endif \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceChatContentListItemView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceChatContentListItemView.h index 0897ec9b0..bde48ec66 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceChatContentListItemView.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceChatContentListItemView.h @@ -29,6 +29,7 @@ namespace OHOS private: UILabel chatContentLabel; + UILabel mindLabel; UIImageView chatContentImage; UIScrollView chatContentScrollView; int m_viewHeight; diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceListeningView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceListeningView.h index d6819659b..c620e77a4 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceListeningView.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceListeningView.h @@ -71,6 +71,7 @@ namespace OHOS static AivoiceListeningView *GetInstance(void); UIScrollView *CreateAivoiceListeningView(void); UILabelExt *GetShowtimeoutLabel(void); + void StartOrStopAivoiceListeningImageAnimatorView(bool val); private: void ClearAll(void); @@ -87,7 +88,6 @@ namespace OHOS UIButton *finishSpeakButton{nullptr}; UIImageAnimatorView *AiVoiceListeningImageAnimatorView{nullptr}; ImageAnimatorInfo AiVoiceListeningImageInfo[AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES]; - const ImageInfo **AiVoiceListeningPathsArray{nullptr}; UILabelExt *showtimeout{nullptr}; }; } diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceReturnResultTextView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceReturnResultTextView.h index 27d9e34aa..f3d8408f6 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceReturnResultTextView.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceReturnResultTextView.h @@ -60,6 +60,7 @@ namespace OHOS UIList *GetChatContentList(void); void UpdateTitleTextId(int textId); void IsScrollChatContentList(bool isScroll); + void SetRequestFocus(); private: void ClearAll(void); diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceThinkingView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceThinkingView.h index d5b7c3487..9bfdd7815 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceThinkingView.h +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceThinkingView.h @@ -64,6 +64,7 @@ namespace OHOS ~AivoiceThinkingView(); static AivoiceThinkingView *GetInstance(void); UIScrollView *CreateAivoiceThinkingView(void); + void StartOrStopAiVoiceThinkingImageAnimatorView(bool val); private: void ClearAll(void); @@ -80,7 +81,6 @@ namespace OHOS UIButton *cancelThinkButton{nullptr}; UIImageAnimatorView *AiVoiceThinkingImageAnimatorView{nullptr}; ImageAnimatorInfo AiVoiceThinkingImageInfo[AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES]; - const ImageInfo **AiVoiceThinkingPathsArray{nullptr}; }; } #endif diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceConnectingView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceConnectingView.cpp index 98b314e63..542b308a1 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceConnectingView.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceConnectingView.cpp @@ -21,6 +21,69 @@ namespace OHOS static constexpr int16_t AIVOICE_CONNECTING_IMAGE_ANIMATOR_DELAY = 50; // 图片更新间隔 static constexpr const char *AIVoiceListeningImagePaths = "/user/res/connect/"; + const char *connecting_path_array[] = { + "/user/res/connect/1.bin", + "/user/res/connect/2.bin", + "/user/res/connect/3.bin", + "/user/res/connect/4.bin", + "/user/res/connect/5.bin", + "/user/res/connect/6.bin", + "/user/res/connect/7.bin", + "/user/res/connect/8.bin", + "/user/res/connect/9.bin", + "/user/res/connect/10.bin", + "/user/res/connect/11.bin", + "/user/res/connect/12.bin", + "/user/res/connect/13.bin", + "/user/res/connect/14.bin", + "/user/res/connect/15.bin", + "/user/res/connect/16.bin", + "/user/res/connect/17.bin", + "/user/res/connect/18.bin", + "/user/res/connect/19.bin", + "/user/res/connect/20.bin", + "/user/res/connect/21.bin", + "/user/res/connect/22.bin", + "/user/res/connect/23.bin", + "/user/res/connect/24.bin", + "/user/res/connect/25.bin", + "/user/res/connect/26.bin", + "/user/res/connect/27.bin", + "/user/res/connect/28.bin", + "/user/res/connect/29.bin", + "/user/res/connect/30.bin", + "/user/res/connect/31.bin", + "/user/res/connect/32.bin", + "/user/res/connect/33.bin", + "/user/res/connect/34.bin", + "/user/res/connect/35.bin", + "/user/res/connect/36.bin", + "/user/res/connect/37.bin", + "/user/res/connect/38.bin", + "/user/res/connect/39.bin", + "/user/res/connect/40.bin", + "/user/res/connect/41.bin", + "/user/res/connect/42.bin", + "/user/res/connect/43.bin", + "/user/res/connect/44.bin", + "/user/res/connect/45.bin", + "/user/res/connect/46.bin", + "/user/res/connect/47.bin", + "/user/res/connect/48.bin", + "/user/res/connect/49.bin", + "/user/res/connect/50.bin", + "/user/res/connect/51.bin", + "/user/res/connect/52.bin", + "/user/res/connect/53.bin", + "/user/res/connect/54.bin", + "/user/res/connect/55.bin", + "/user/res/connect/56.bin", + "/user/res/connect/57.bin", + "/user/res/connect/58.bin", + "/user/res/connect/59.bin", + "/user/res/connect/60.bin", + }; + static AiVoiceConnectingView *g_pAiVoiceConnecting{nullptr}; AiVoiceConnectingView::AiVoiceConnectingView() { @@ -50,7 +113,10 @@ namespace OHOS connectingAnimatorView->Stop(); delete connectingAnimatorView; connectingAnimatorView = nullptr; - FreeImageInfoArray(connectingPathsArray, AIVoiceListeningImagePaths, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); + for (int i = 0; i < AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++) + { + ImageCacheManager::GetInstance().UnloadSingleRes(connecting_path_array[i]); + } } if (cancelLabel) { @@ -220,35 +286,31 @@ namespace OHOS bool AiVoiceConnectingView::CreateAivoiceConnectingImageAnimator(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::CreateAivoiceConnectingImageAnimator"); - if (connectingPathsArray == nullptr) - { - connectingPathsArray = CreateImageInfoArray(AIVoiceListeningImagePaths, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); - if (connectingPathsArray == nullptr) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::connectingPathsArray is nullptr!!"); - return false; - } - } - - ImageAnimatorConfig imageanimatorconfig = { - .x = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_X, - .y = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_Y, - .width = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_W, - .height = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_H, - .imageInfoArray = connectingImageInfo, - .pathsArray = connectingPathsArray, - .numFrames = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, - .delay = AIVOICE_CONNECTING_IMAGE_ANIMATOR_DELAY, - }; if (connectingAnimatorView == nullptr) { - connectingAnimatorView = connectingImageAnimatorInit(imageanimatorconfig); + connectingAnimatorView = new UIImageAnimatorView(); if (connectingAnimatorView == nullptr) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::connectingAnimatorView new fail"); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::CreateAivoiceConnectingImageAnimator new connectingAnimatorView fail"); return false; } } + for (uint8_t i = 0; i < AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++) + { + connectingImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(connecting_path_array[i]); + connectingImageInfo[i].imageType = IMG_SRC_IMAGE_INFO; + connectingImageInfo[i].pos.x = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_X; + connectingImageInfo[i].pos.y = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_Y; + connectingImageInfo[i].width = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_W; + connectingImageInfo[i].height = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_H; + } + connectingAnimatorView->SetPosition(AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_X, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_Y, + AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_W, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_H); + connectingAnimatorView->SetImageAnimatorSrc(connectingImageInfo, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, AIVOICE_CONNECTING_IMAGE_ANIMATOR_DELAY); + connectingAnimatorView->SetRepeat(true); + connectingAnimatorView->SetAutoEnable(false); + connectingAnimatorView->SetResizeMode(UIImageView::FILL); + connectingAnimatorView->Start(); return true; } diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp index 81676d564..9b3ec27b1 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp @@ -6,6 +6,7 @@ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp */ #include "aivoice/include/AiVoiceModel.h" +#include "aivoice/include/AiVoiceModelC.h" #include "aivoice/include/AiVoicePresenter.h" #include "aivoice/include/AiVoiceView.h" #include "aivoice/include/AivoiceReturnResultTextView.h" @@ -30,6 +31,10 @@ #include #include #include +#include "custom_runtime.h" +#include "cat1_ws.h" +#include "voice_call_volte_sample_wrapper.h" +#include namespace OHOS { // 声明定时器变量 @@ -150,38 +155,57 @@ namespace OHOS // 获取APP蓝牙是否已连接 bool AiVoiceModel::GetAPPBluetoothIsConnect(void) { - // return SettingModel::GetInstance().GetPhoneConnectStatus(); - - #ifdef SUPPORT_BLE_SERVICE +#ifdef SUPPORT_BLE_SERVICE return get_ble_connect(); - #else - return false; - #endif +#else + return false; +#endif } // 获取4G网络是否正常 bool AiVoiceModel::GetMobileDataIsOpen(void) { + if (uapi_dev_runtime_get_cat1_networkstat() == 1) + { + return true; + } return false; } /*查询用户选择的AI模型是否已经连接*/ void AiVoiceModel::QuerySelectedAiModelIsConnect() { - #ifdef SUPPORT_BLE_SERVICE auto it = selectAiModelToTextId.find(GetSelectAiModel()); if (it != selectAiModelToTextId.end()) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[QuerySelectedAiModelIsConnect] SelectAiModel = %d", it->second.second); - inquire_AI_is_ready(it->second.second); + if (GetSelect4gorbt() == AI_SELECT_4G) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelect4gorbt() == AI_SELECT_4G"); + if (GetInit_4gai_task()) + { +#if AI_VOICE_ENABLE + uapi_UI_start_asr(GetCurUsing4GAiModelType()); +#endif + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "init_4gai_task fail!!"); + } + } + else if (GetSelect4gorbt() == AI_SELECT_BT) + { +#ifdef SUPPORT_BLE_SERVICE + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "蓝牙:查询Ai是否就绪"); + inquire_AI_is_ready(it->second.second); +#endif + } } - #endif } // 获取当前正在使用的AI模型 uint8_t AiVoiceModel::GetCurUsingAiModelType(void) { - auto it = selectAiModelToTextId.find(GetSelectAiModel()); if (it != selectAiModelToTextId.end()) { @@ -190,13 +214,32 @@ namespace OHOS return 0; } + uint8_t AiVoiceModel::GetCurUsing4GAiModelType(void) + { +#if AI_VOICE_ENABLE + int value = GetSelectAiModel(); + std::map> selectAiModelToAiModelType = { + {0, {STR_DEEPSEEK, AI_TYPE_DE}}, + {1, {STR_JIUTIAN, AI_TYPE_JIU}}, + {2, {STR_AIMODELS_DOUBAO, AI_TYPE_DOU}}, + {3, {STR_AIMODES_WENXINYIYAN, AI_TYPE_WEN}}, + {4, {STR_AIMODES_KIMI, AI_TYPE_KIMI}}, + {5, {STR_AIMODES_CHATGPT, AI_TYPE_0}}, + }; + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetCurUsing4GAiModelType = %d", selectAiModelToAiModelType[value].second); + return selectAiModelToAiModelType[value].second; +#endif + return 0; + } + /*取消当前AI对话*/ void AiVoiceModel::CancelCurAIChat(void) { - // cancel_AI_cur_chat(); //线程发送取消当前对话 - #ifdef SUPPORT_BLE_SERVICE - cancel_AI_cur_chat_();// 直接发送取消当前对话 - #endif +// cancel_AI_cur_chat(); //线程发送取消当前对话 +#ifdef SUPPORT_BLE_SERVICE + cancel_AI_cur_chat_(); // 直接发送取消当前对话 +#endif } int AiVoiceModel::GetAIResponseType(void) @@ -232,6 +275,11 @@ namespace OHOS return ChatContentListCount; } + void AiVoiceModel::SetChatContentListCount(uint8_t count) + { + ChatContentListCount = count; + } + /*添加聊天内容项到数组*/ bool AiVoiceModel::AddChatContentToItemArray(const ChatContentItem &item) { @@ -360,7 +408,7 @@ namespace OHOS { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::UpdateUserQuestionStr"); - if(!RemoveLastTwoItemsOrClear()) + if (!RemoveLastTwoItemsOrClear()) { return false; } @@ -399,24 +447,6 @@ namespace OHOS bool AiVoiceModel::UpdateAiAnswerStr() { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::UpdateAiAnswerStr"); - #if 0 - AiVoiceView *view_ = AiVoiceView::GetInstance(); - if(view_!= nullptr ) - { - if(view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && !view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible()) - { - return false; - } - else - { - if(!GetIsClickable()) - { - SetIsClickable(true); - } - } - } - #endif - int index = GetChatContentListCount() - 1; if (index < 0 || index >= MaxChatContentListCount) { @@ -455,7 +485,7 @@ namespace OHOS // 将更新后的 AI 回答内容添加到列表 adapter->GetChatContentItem().push_back(chatTtems[GetChatContentListCount() - 1]); if (AiVoicePresenter::GetInstance()) - AiVoicePresenter::GetInstance()->calculateChatContentItemViewHeight(chatTtems[GetChatContentListCount() - 1].text, true); + AiVoicePresenter::GetInstance()->calculateChatContentItemViewHeight(chatTtems[GetChatContentListCount() - 1].text, true); p_AivoiceReturnResultTextView->GetChatContentList()->RefreshList(); } else @@ -471,7 +501,7 @@ namespace OHOS { isClickable = value; } - + bool AiVoiceModel::GetIsClickable(void) { return isClickable; @@ -497,22 +527,38 @@ namespace OHOS /*设置用户问题的字符串*/ void AiVoiceModel::SetUserQuestionStr(std::string str) { - if (!entryTextViewState) + if (GetSelect4gorbt() == AI_SELECT_4G) + { + if (str.empty()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "传入的问题为空"); + return; + } + userQuestionStr += str; + if (!entryTextViewState) + { + SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0); + entryTextViewState = true; // 进入返回结果界面的标志 避免重复发消息 + usleep(50000); // 延时等待创建完成,0.05秒 + } + /* -------------------------------------------------------------------------- */ + SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0); + } + else if (GetSelect4gorbt() == AI_SELECT_BT) { - #ifdef SUPPORT_BLE_SERVICE - SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0); - #endif - entryTextViewState = true; // 进入返回结果界面的标志 避免重复发消息 - usleep(50000); // 延时等待创建完成,0.05秒 + if (!entryTextViewState) + { + SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0); + entryTextViewState = true; // 进入返回结果界面的标志 避免重复发消息 + usleep(50000); // 延时等待创建完成,0.05秒 + } + /* -------------------------------------------------------------------------- */ + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "传入的问题:%s", str.c_str()); + userQuestionStr = str; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "拼接的问题:%s", userQuestionStr.c_str()); + /* -------------------------------------------------------------------------- */ + SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0); } - /* -------------------------------------------------------------------------- */ - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "传入的问题:%s",str.c_str()); - userQuestionStr = str; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "拼接的问题:%s",userQuestionStr.c_str()); - /* -------------------------------------------------------------------------- */ - #ifdef SUPPORT_BLE_SERVICE - SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0); - #endif } /*获取Ai回答的字符串*/ @@ -527,50 +573,330 @@ namespace OHOS void AiVoiceModel::SetAiAnswerStrStr(std::string str) { aiAnswerStr += str; - #ifdef SUPPORT_BLE_SERVICE SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0); - #endif } - void AiVoiceModel::SetAiAnswerStrStr(std::string str, uint8_t type) + // 安全替换 UTF-8 字符串中的字符 + static void safe_replace_utf8(std::string &str, const std::string &from_chars, char replacement) { - AIResponseType = type; - errnote = str; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AIResponseType = %d,errnote = %s\n", AIResponseType, errnote.c_str()); - //如果是:AI录音解析错误或AI 回应错误 ,或者重传多次录音数据->跳转AI回应错误界面 - if (AIResponseType == AiVoiceModel::AI_RECORDING_PARSING_ERROR || AIResponseType == AiVoiceModel::AI_RESPONSE_ERROR - || AIResponseType == AiVoiceModel::AI_BLE_ERROR) - { - #ifdef SUPPORT_BLE_SERVICE - SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)errnote.c_str(), errnote.length()); - #endif + std::string result; + result.reserve(str.length()); // 预分配足够空间 + + const char *p = str.c_str(); + const char *end = p + str.length(); + + while (p < end) + { + unsigned char c = *p; + size_t char_size = 1; + + // 判断 UTF-8 字符的字节数 + if ((c & 0x80) == 0) + { + // 1字节字符 (ASCII) + char_size = 1; + } + else if ((c & 0xE0) == 0xC0) + { + // 2字节字符 + char_size = 2; + } + else if ((c & 0xF0) == 0xE0) + { + // 3字节字符 (常见中文) + char_size = 3; + } + else if ((c & 0xF8) == 0xF0) + { + // 4字节字符 (如 Emoji) + char_size = 4; + } + else + { + // 无效字符,按单字节处理 + char_size = 1; + } + + // 检查字符是否在要替换的集合中 + bool replace = false; + if (char_size == 1) + { + // 单字节字符直接检查 + replace = (from_chars.find(c) != std::string::npos); + } + else + { + // 多字节字符,提取完整字符并检查 + std::string utf8_char(p, char_size); + for (size_t i = 0; i < from_chars.length();) + { + // 提取 from_chars 中的下一个 UTF-8 字符 + unsigned char fc = from_chars[i]; + size_t fc_size = 1; + + if ((fc & 0x80) == 0) + { + fc_size = 1; + } + else if ((fc & 0xE0) == 0xC0) + { + fc_size = 2; + } + else if ((fc & 0xF0) == 0xE0) + { + fc_size = 3; + } + else if ((fc & 0xF8) == 0xF0) + { + fc_size = 4; + } + + if (i + fc_size <= from_chars.length()) + { + std::string fc_str = from_chars.substr(i, fc_size); + if (fc_str == utf8_char) + { + replace = true; + break; + } + } + + i += fc_size; + } + } + + // 添加到结果字符串 + if (replace) + { + result += replacement; + } + else + { + result.append(p, char_size); + } + + p += char_size; + } + + // 替换原字符串 + str.swap(result); + } + + static int fouce_count = 0; // + void AiVoiceModel::ProcessTextByPunctuation() + { + const std::string punctuation = ",。!?;:))“”、\"\""; // 要替换的中文标点 + const char replacement = ','; // 替换为英文逗号 + const size_t MAX_SEGMENT_LENGTH = 120; // 最大分段长度 + const size_t MIN_SEGMENT_LENGTH = 1; // 最小发送长度(可调整) + + if (accumulatedText.empty()) return; + + // 安全替换中文标点为英文逗号 + std::string processedText = accumulatedText; + safe_replace_utf8(processedText, punctuation, replacement); + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "processedText:%s", processedText.c_str()); + + accumulatedText = processedText; + size_t commaPos = accumulatedText.find_last_of(','); + + // 处理长度限制,若超过最大长度则强制分段 + if (accumulatedText.length() >= MAX_SEGMENT_LENGTH) + { + commaPos = MAX_SEGMENT_LENGTH - 1; + // 查找最大长度内最近的逗号 + size_t lastCommaInRange = accumulatedText.find_last_of(',', commaPos); + if (lastCommaInRange != std::string::npos) + { + commaPos = lastCommaInRange; + } + } + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "commaPos:%d", commaPos); + + if (commaPos != std::string::npos) + { + // 按标点分段发送 + sendSegment(accumulatedText, commaPos); } - else if (AiVoiceModel::AI_RESPONSE_END) // 如果是AI 回应结束 + else { - if (errnote.empty()) // 如果没有回应数据 + // 无逗号时的处理逻辑 + if (accumulatedText.length() >= MIN_SEGMENT_LENGTH) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::GetErrnote is empty!!"); - AiVoiceModel::GetInstance().SetErrnote("响应内容为空"); - std::string str = AiVoiceModel::GetInstance().GetErrnote(); - #ifdef SUPPORT_BLE_SERVICE - SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length()); - #endif - return; + // 强制发送完整文本(无论是否有标点) + std::string segment = accumulatedText; + segment.erase( + std::remove(segment.begin(), segment.end(), '\n'), + segment.end()); + segment.erase( + std::remove(segment.begin(), segment.end(), '\r'), + segment.end()); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "强制发送文本: %s (长度: %zu)", + segment.c_str(), segment.length()); + bool sendret = false; +#if AI_VOICE_ENABLE + sendret = uapi_start_tts_single_txt((char *)segment.c_str()); +#endif + // 如果为true发送成功,如果发送失败等待下次发送不清空文本 + if (sendret) + { + // 发送后清空累积文本 + accumulatedText.clear(); + fouce_count = 0; + } + else + { + // 发送失败,等待下次发送 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败,等待下次发送,fouce_count:%d", fouce_count); + fouce_count++; + if (fouce_count >= 3 && !hasTtsStartSucceeded) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败准备发送:uapi_start_tts有且只发一次"); + bool startOk = false; +#if AI_VOICE_ENABLE + startOk = uapi_start_tts(); +#endif + fouce_count = 0; + if (startOk) + { + hasTtsStartSucceeded = true; + } + } + } + } + else + { + // 文本过短,继续累积 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "累积文本过短(长度: %zu), 继续累积", + accumulatedText.length()); + } + } + } + + // 辅助函数:按标点分段发送 + void AiVoiceModel::sendSegment(const std::string &text, size_t pos) + { + // 提取分段(包含英文逗号) + std::string segment = text.substr(0, pos + 1); + + // 清理文本 + segment.erase( + std::remove(segment.begin(), segment.end(), '\n'), + segment.end()); + segment.erase( + std::remove(segment.begin(), segment.end(), '\r'), + segment.end()); + + // 发送到TTS播放 + bool ret = false; + if (!segment.empty()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "按标点发送分段: %s (长度: %zu)", + segment.c_str(), segment.length()); +#if AI_VOICE_ENABLE + ret = uapi_start_tts_single_txt((char *)segment.c_str()); +#endif + } + + if (ret) + { + // 更新累积文本 + if (pos + 1 < text.length()) + { + accumulatedText = text.substr(pos + 1); + } + else + { + accumulatedText.clear(); + } + fouce_count = 0; + } + else + { + // 发送失败,等待下次发送 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败,等待下次发送,fouce_count:%d", fouce_count); + fouce_count++; + if (fouce_count >= 3 && !hasTtsStartSucceeded) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败准备发送:uapi_start_tts有且只发一次"); + bool startOk = false; +#if AI_VOICE_ENABLE + startOk = uapi_start_tts(); +#endif + fouce_count = 0; + if (startOk) + { + hasTtsStartSucceeded = true; + } } } + } + + std::string AiVoiceModel::GetAccumulatedText(void) + { + return accumulatedText; + } + + void AiVoiceModel::SetAiAnswerStrStr(std::string str, uint8_t type) + { + AIResponseType = type; + errnote = str; AiVoiceView *view_ = AiVoiceView::GetInstance(); - if(view_!= nullptr ) + if (GetSelect4gorbt() == AI_SELECT_4G) // 4G + { + if (!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) // 如果ai答案没有显示到极限了,就更新ai答案字符串 + { + delete_start_line_break_str(str); + aiAnswerStr += str; + /* -------------------------------------------------------------------------- */ + // 累积接收到的文本 + accumulatedText += str; + /* -------------------------------------------------------------------------- */ + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str()); + } + if (view_ != nullptr) + { + if (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible()) + { + start_ai4g_tts_play_timer(); // 开启一个定时器,用于播放tts音频 + start_update_ai_answer_timer(); + } + } + } + else if (GetSelect4gorbt() == AI_SELECT_BT) // 蓝牙 { - if(view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible()) + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AIResponseType = %d,errnote = %s\n", AIResponseType, errnote.c_str()); + // 如果是:AI录音解析错误或AI 回应错误 ,或者重传多次录音数据->跳转AI回应错误界面 + if (AIResponseType == AiVoiceModel::AI_RECORDING_PARSING_ERROR || AIResponseType == AiVoiceModel::AI_RESPONSE_ERROR || AIResponseType == AiVoiceModel::AI_BLE_ERROR) + { + SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)errnote.c_str(), errnote.length()); + return; + } + else if (AiVoiceModel::AI_RESPONSE_END) // 如果是AI 回应结束 + { + if (errnote.empty()) // 如果没有回应数据 + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::GetErrnote is empty!!"); + AiVoiceModel::GetInstance().SetErrnote("响应内容为空"); + std::string str = AiVoiceModel::GetInstance().GetErrnote(); + SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length()); + return; + } + } + if (view_ != nullptr) { - if(!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) //如果ai答案没有显示到极限了,就更新ai答案字符串 - { - aiAnswerStr += str; - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str()); - #ifdef SUPPORT_BLE_SERVICE - SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0); - #endif + if (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible()) + { + if (!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) // 如果ai答案没有显示到极限了,就更新ai答案字符串 + { + aiAnswerStr += str; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str()); + SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0); + } } } } @@ -582,6 +908,8 @@ namespace OHOS WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "清空上次用户问题和Ai回答字符串"); userQuestionStr = ""; aiAnswerStr = ""; + accumulatedText = ""; + set_is_first_receive(true); } /*获取AI音频路径*/ @@ -596,7 +924,7 @@ namespace OHOS #endif int32_t AudioCaptureSample(int32_t argc, const char *argv[]); int32_t streamingRecordAndSend_AI(int type); - #define IS_SUPPORT_REALTIME_RECORD_SEND_AI 1 //是否支持实时发送录音数据 +#define IS_SUPPORT_REALTIME_RECORD_SEND_AI 1 // 是否支持实时发送录音数据 #ifdef __cplusplus }; #endif @@ -617,9 +945,17 @@ namespace OHOS #if IS_SUPPORT_REALTIME_RECORD_SEND_AI int type = GetCurUsingAiModelType(); WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "type = %d", type); - #ifdef SUPPORT_BLE_SERVICE - streamingRecordAndSend_AI(type);//实时发送录音数据 - #endif + if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT) + { + streamingRecordAndSend_AI(type); // 实时发送录音数据 + } + else if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G) + { +#if AI_VOICE_ENABLE + LOS_Msleep(20); + startAudioCaptureTask(); +#endif + } #else std::string audioPath = AiVoiceModel::GetInstance().GetAIAudioPath(); if (uapi_delete_files(audioPath.c_str())) // 先删除文件 @@ -637,8 +973,8 @@ namespace OHOS #elif CURRENT_AIAUDIO_TYPE == AIAUDIO_TYPE_MSBC const char *defaultArgs[6] = {"01", "msbc", "16000", "1", "16", audioPath.c_str()}; #endif - uapi_save_runtime_log(RUNTIME_LOG_RECORD_START_AI);//TOOD* - AudioCaptureSample(6, (const char **)defaultArgs); + uapi_save_runtime_log(RUNTIME_LOG_RECORD_START_AI); // TOOD* + AudioCaptureSample(6, (const char **)defaultArgs); #endif } return; @@ -648,74 +984,43 @@ namespace OHOS void AiVoiceModel::StopListenAndRecordingUserQuestion(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "停止录音"); - int32_t argc = 1; - uint8_t *argv = (uint8_t *)"stop"; - AudioCaptureSample(argc, (const char **)&argv); - uapi_save_runtime_log(RUNTIME_LOG_RECORD_STOP_AI);//TOOD* - return; - } - - /*检查录音文件是否存在并发送语音准备操作*/ - void AiVoiceModel::CheckFileAndSendAIIsReady(void) - { - #ifdef SUPPORT_BLE_SERVICE - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::CheckFileAndSendAIIsReady"); - const std::string &filePath = AIAIAudioPath; - FILE *file = fopen(filePath.c_str(), "r"); - if (file != nullptr) + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "停止录音:%d", GetSelect4gorbt()); + if (GetSelect4gorbt() == AI_SELECT_4G) // 选的是4G需要关闭asr { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "File already exists: %s", filePath.c_str()); - - fseek(file, 0, SEEK_END); - long size = ftell(file); - fseek(file, 0, SEEK_SET); - if (size != 0) - { - auto it = selectAiModelToTextId.find(GetSelectAiModel()); - if (it != selectAiModelToTextId.end()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "filesize = %ld,SelectAiModel = %d", size, it->second.second); - if(get_ble_interval() >= BLE_CONNECT_INTERVAL_SLOW) - { - uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH); - } - send_AI_is_ready(it->second.second); - } - else - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelectAiModel fail!!", size, it->second.second); - } - - ClearQuestionAndAiAnswerStr(); // 清空上次用户问题和Ai回答字符串 - } - fclose(file); + // uapi_stop_asr(); + // stop_AudioCaptureProcess_AI(); + // uapi_UI_stop_asr(); } - else + else if (GetSelect4gorbt() == AI_SELECT_BT) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File does not exist: %s", filePath.c_str()); - // Handle the case where the file doesn't exist, if needed + int32_t argc = 1; + uint8_t *argv = (uint8_t *)"stop"; + AudioCaptureSample(argc, (const char **)&argv); } - #endif + uapi_save_runtime_log(RUNTIME_LOG_RECORD_STOP_AI); // TOOD* + return; } void AiVoiceModel::sendAIIsReady() { - #ifdef SUPPORT_BLE_SERVICE +#ifdef SUPPORT_BLE_SERVICE auto it = selectAiModelToTextId.find(GetSelectAiModel()); if (it != selectAiModelToTextId.end()) { - // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "filesize = %ld,SelectAiModel = %d", size, it->second.second); - if(get_ble_interval() >= BLE_CONNECT_INTERVAL_SLOW) + + if (get_ble_interval() >= BLE_CONNECT_INTERVAL_SLOW) { uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH); } send_AI_is_ready(it->second.second); } - #endif +#endif } void AiVoiceModel::StatusResume(void) { + ClearQuestionAndAiAnswerStr(); + StopListenAndRecordingUserQuestion(); Time = THIRTY_TIME; AiModelConnectTimeout = 5; AiVoiceConnectStatus = false; @@ -730,8 +1035,10 @@ namespace OHOS entryTextViewState = false; isClickable = false; isLimitDisplayed = false; - ClearQuestionAndAiAnswerStr(); - StopListenAndRecordingUserQuestion(); + AI_4G_state = false; + AI_BT_state = false; + select4gorbt = -1; + // init_4gai_task = false;//TOOD:之后需要销毁 } /* -------------------------------------------------------------------------- */ @@ -745,24 +1052,30 @@ namespace OHOS AiVoiceModel::GetInstance().AIVoice_StopTimer(); AiVoiceModel::GetInstance().SetErrnote("连接超时,请重新开始对话"); std::string str = AiVoiceModel::GetInstance().GetErrnote(); - #ifdef SUPPORT_BLE_SERVICE +#if AI_VOICE_ENABLE + dinit_ai_task(); // 所有服务都删除重新连一下服务器 +#endif SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length()); - #endif } else { - #ifdef SUPPORT_BLE_SERVICE - // 4g中途断连待扩展 - // 蓝牙的连接状态判断,如果AI思考过程中途断连,直接弹窗提示,不在硬等 - if (get_ble_connect() == false) + if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G) + { + if (AiVoiceModel::GetInstance().is_need_to_jump_result_view()) + { + SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0); // 跳转到结果界面 + } + return; + } + else if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT) { - AiVoiceModel::GetInstance().SetErrnote("手机蓝牙已断开"); - std::string str = AiVoiceModel::GetInstance().GetErrnote(); - #ifdef SUPPORT_BLE_SERVICE - SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length()); - #endif + if (AiVoiceModel::GetInstance().GetAPPBluetoothIsConnect() == false) // 蓝牙的连接状态判断,如果AI思考过程中途断连,直接弹窗提示,不在硬等 + { + AiVoiceModel::GetInstance().SetErrnote("手机蓝牙已断开"); + std::string str = AiVoiceModel::GetInstance().GetErrnote(); + SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length()); + } } - #endif } return; } @@ -852,8 +1165,10 @@ namespace OHOS { // 60s后息屏停止定时 AiVoiceModel::GetInstance().ai_stop_screen60s_timer(); - // 取消常亮屏 - ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); + if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT) + { + ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); // 取消常亮屏 + } } } static void ai_start_screen60s_timer_callback(int data) @@ -914,7 +1229,7 @@ namespace OHOS void AiVoiceModel::reset_ai_screen60s_timer_time() { SCREEN_60S_TIME = 60; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "reset_ai_screen60s_timer_time %d", SCREEN_60S_TIME); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "reset_ai_screen60s_timer_time %d", SCREEN_60S_TIME); if (nullptr == g_screen60s_timer) { ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); // 重新常亮屏 @@ -924,7 +1239,7 @@ namespace OHOS bool AiVoiceModel::get_screen60s_timer_is_stop(void) { - if(g_screen60s_timer == nullptr) + if (g_screen60s_timer == nullptr) return true; else return false; @@ -937,12 +1252,14 @@ namespace OHOS LISTENING_TIMEOUT--; if (LISTENING_TIMEOUT <= 0) { - AiVoiceModel::GetInstance().StopListenAndRecordingUserQuestion(); // 停止聆听用户问题 - AiVoiceModel::GetInstance().stop_listening_timer(); // 停止聆听定时器 - if (AiVoiceView::GetInstance() && AivoiceListeningView::GetInstance()) + AiVoiceModel::GetInstance().stop_listening_timer(); // 停止聆听定时器 + AiVoicePresenter *p_AiVoicePresenter = AiVoicePresenter::GetInstance(); + if (AiVoicePresenter::GetInstance() && AivoiceListeningView::GetInstance()) { - AiVoiceView::GetInstance()->ChangeView(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); // 切换到思考中界面 - AiVoiceModel::GetInstance().AIVoice_StartTimer(); +#if AI_VOICE_ENABLE + uapi_UI_stop_asr(); +#endif + AiVoicePresenter::GetInstance()->ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); // 切换到思考中界面 } } else @@ -1014,7 +1331,7 @@ namespace OHOS } static osTimerId_t g_ai_is_ready_Handle = nullptr; // 处理查询AI是否就绪定时器 - static int8_t AI_IS_READY_TIMEOUT = 5; // 5s钟超时 + static int8_t AI_IS_READY_TIMEOUT = 5; // 5s钟超时 static void AI_IS_READY_CallbackProc(int data) { if (AI_IS_READY_TIMEOUT <= 0) // 模型连接失败有5秒超时 @@ -1027,10 +1344,32 @@ namespace OHOS if ((view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr) && (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible())) { +#if AI_VOICE_ENABLE + dinit_ai_task(); // 所有服务都删除重新连一下服务器 +#endif p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID); } } } + else + { + if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelect4gorbt() == AI_SELECT_4G"); + if (AiVoiceModel::GetInstance().GetInit_4gai_task()) + { + uint8_t state = 0; +#if AI_VOICE_ENABLE + state = get_asr_is_ready_start(); +#endif + if (state) + { + bool state = true; + SendMsgToUIService(UI_AI_JUMP_TO_LISTENING_VIEW, 0, &state, sizeof(bool)); + } + } + } + } return; } static void AI_IS_READY_Callback(int data) @@ -1094,34 +1433,495 @@ namespace OHOS } } - // 设置选择的ai模型 - void AiVoiceModel::SetSelectAiModel(int index) - { - ConfigModel::GetInstance()->SetSelectAiModel(index); - } - - int AiVoiceModel::GetSelectAiModel(void) - { - return ConfigModel::GetInstance()->GetSelectAiModel(); - } - - /*获取已选择的ai模型的textid*/ - int AiVoiceModel::GetAiModelTextId() + /* -------------------------------------------------------------------------- */ + static osTimerId_t g_ai4g_is_suc_connected_Handle = nullptr; // 处理AI4G连接定时器 + static uint8_t AI4G_IS_SUC_CON_TIME = 25; + static int8_t AI4G_IS_SUC_CON_TIMEOUT = AI4G_IS_SUC_CON_TIME; // AI4G_IS_SUC_CON_TIME秒超时 + static void AI4G_IS_SUC_CON_CallbackProc(int data) { - #if 0 - int language = ConfigModel::GetInstance()->GetLanguage(); - int textId; - - if (language == 0) + AiVoiceView *view_ = AiVoiceView::GetInstance(); + AiVoicePresenter *p_AiVoicePresenter = AiVoicePresenter::GetInstance(); + if (AI4G_IS_SUC_CON_TIMEOUT <= 0) // 4g服务器连接失败 { - selectAiModelToTextId = { - {0, {STR_AIMODES_WENXINYIYAN, 0}}, + AiVoiceModel::GetInstance().stop_ai4g_connect_timer(); + if (view_ != nullptr && p_AiVoicePresenter != nullptr) + { + if ((view_->GetAiVoiceScrollView(AIVOICE_4GSERVICECON_VIEW) != nullptr) && + (view_->GetAiVoiceScrollView(AIVOICE_4GSERVICECON_VIEW)->IsVisible())) + { +#if AI_VOICE_ENABLE + dinit_ai_task(); // 所有服务都删除重新连一下服务器 +#endif + p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_4GSERVICECON_VIEW, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID); + } + } + } + else + { + if (view_ != nullptr && p_AiVoicePresenter != nullptr) + { +#if AI_VOICE_ENABLE + if (uapi_get_server_state_is_end()) + { + init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType()); + return; + } + + if (AiVoiceModel::GetInstance().GetInit_4gai_task()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "4gAi服务初始化成功"); + AiVoiceModel::GetInstance().stop_ai4g_connect_timer(); + p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_4GSERVICECON_VIEW, AIVOICE_AIMODE_CONNECTING); + } +#endif + } + } + return; + } + static void AI4G_IS_SUC_CON_Callback(int data) + { + AI4G_IS_SUC_CON_TIMEOUT--; + GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_IS_SUC_CON_CallbackProc, data)); + } + /*处理AI4G连接定时器到期时的处理*/ + void AiVoiceModel::start_ai4g_connect_timer(uint32_t interval) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_ai4g_connect_timer"); + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_ai4g_is_suc_connected_Handle != nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!"); + return; + } + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_ai4g_is_suc_connected_Handle = osTimerNew((osTimerFunc_t)AI4G_IS_SUC_CON_Callback, osTimerPeriodic, nullptr, nullptr); + // 检查定时器创建是否成功 + if (g_ai4g_is_suc_connected_Handle == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!"); + return; + } + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + /* --------------------------------- 4.启动定时器 -------------------------------- */ + osStatus_t ret = osTimerStart(g_ai4g_is_suc_connected_Handle, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + if (g_ai4g_is_suc_connected_Handle != nullptr) + { + ret = osTimerDelete(g_ai4g_is_suc_connected_Handle); + } + g_ai4g_is_suc_connected_Handle = nullptr; + return; + } + return; + } + + void AiVoiceModel::stop_ai4g_connect_timer(void) + { + // 检查定时器是否存在 + if (g_ai4g_is_suc_connected_Handle != nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::stop_ai4g_connect_timer"); + osTimerStop(g_ai4g_is_suc_connected_Handle); + // 删除定时器并置为 nullptr + osStatus_t ret = osTimerDelete(g_ai4g_is_suc_connected_Handle); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + } + g_ai4g_is_suc_connected_Handle = nullptr; + AI4G_IS_SUC_CON_TIMEOUT = AI4G_IS_SUC_CON_TIME; + } + } + + /* -------------------------------- tts播放定时器 -------------------------------- */ + static osTimerId_t g_ai4g_is_start_tts_play_Handle = nullptr; + static constexpr const int8_t NUMBER_TEN = 15; + static int8_t AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN; + static uint8_t tts_record_flag = 0; + // 添加一个静态变量用于跟踪连续出现0的次数 + static int s_tts_tick_zero_count = 0; + static void AI4G_IS_START_TTS_CallbackProc(int data) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AI4G_IS_START_TTS_CallbackProc:%s", AiVoiceModel::GetInstance().GetAccumulatedText().c_str()); + AiVoiceModel::GetInstance().GetInit_4gai_task(); // 获取4gai服务状态 + uint8_t tts_state = 0; +#if AI_VOICE_ENABLE + tts_state = get_ai_tts_server_init_flag(); +#endif + if (tts_state == 0) // tts服务如果断开了,就停止定时器 + { + s_tts_tick_zero_count++; // 增加连续0的次数 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "s_tts_tick_zero_count count: %d", s_tts_tick_zero_count); + if (s_tts_tick_zero_count >= 10) // 如果连续出现10次0,就停止定时器 + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "tts_server disconnect..."); + AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer(); + return; + } + } + + // 无文本时停止定时器 + if (AiVoiceModel::GetInstance().GetAccumulatedText().empty()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "没有文本了准备发送:stop_ai4g_tts_play_timer"); + AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer(); + return; + } + +#if AI_VOICE_ENABLE + if (!get_ai_osal_msg_queue_is_full()) + { + AiVoiceModel::GetInstance().ProcessTextByPunctuation(); + } +#endif + return; + } + + static void AI4G_IS_START_TTS_Callback(int data) + { + AI4G_IS_START_TTS_CallbackProc(data); + // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_IS_START_TTS_CallbackProc, data)); + } + + void AiVoiceModel::start_ai4g_tts_play_timer(uint32_t interval) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_ai4g_tts_play_timer"); + // AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN; + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_ai4g_is_start_tts_play_Handle != nullptr) + { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!"); + return; + } + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_ai4g_is_start_tts_play_Handle = osTimerNew((osTimerFunc_t)AI4G_IS_START_TTS_Callback, osTimerPeriodic, nullptr, nullptr); + // 检查定时器创建是否成功 + if (g_ai4g_is_start_tts_play_Handle == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!"); + return; + } + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + /* --------------------------------- 4.启动定时器 -------------------------------- */ + osStatus_t ret = osTimerStart(g_ai4g_is_start_tts_play_Handle, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + if (g_ai4g_is_start_tts_play_Handle != nullptr) + { + ret = osTimerDelete(g_ai4g_is_start_tts_play_Handle); + } + g_ai4g_is_start_tts_play_Handle = nullptr; + return; + } + return; + } + + void AiVoiceModel::stop_ai4g_tts_play_timer(void) + { + // 检查定时器是否存在 + if (g_ai4g_is_start_tts_play_Handle != nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stop_ai4g_tts_play_timer"); + osTimerStop(g_ai4g_is_start_tts_play_Handle); + // 删除定时器并置为 nullptr + osStatus_t ret = osTimerDelete(g_ai4g_is_start_tts_play_Handle); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + } + g_ai4g_is_start_tts_play_Handle = nullptr; + AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN; + s_tts_tick_zero_count = 0; // 重置计数器 + fouce_count = 0; + + start_uapi_stop_tts_timer(); + } + } + + static osTimerId_t g_start_ai_answer_update_Handle = nullptr; + static constexpr const int8_t NUMBER_THREE = 3; + static int8_t START_UPDATE_AIANSWER_CNT = NUMBER_THREE; + static void AI4G_START_AI_ANSWER_CallbackProc(int data) + { + START_UPDATE_AIANSWER_CNT--; + if (START_UPDATE_AIANSWER_CNT <= 0) + { + AiVoiceModel::GetInstance().stop_update_ai_answer_timer(); + } + else + { + SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0); + } + } + + static void AI4G_START_AI_ANSWER_Callback(int data) + { + AI4G_START_AI_ANSWER_CallbackProc(data); + // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_START_AI_ANSWER_CallbackProc, data)); + } + + void AiVoiceModel::start_update_ai_answer_timer(uint32_t interval) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_update_ai_answer_timer"); + START_UPDATE_AIANSWER_CNT = NUMBER_THREE; + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_start_ai_answer_update_Handle != nullptr) + { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!"); + return; + } + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_start_ai_answer_update_Handle = osTimerNew((osTimerFunc_t)AI4G_START_AI_ANSWER_Callback, osTimerPeriodic, nullptr, nullptr); + // 检查定时器创建是否成功 + if (g_start_ai_answer_update_Handle == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!"); + return; + } + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + /* --------------------------------- 4.启动定时器 -------------------------------- */ + osStatus_t ret = osTimerStart(g_start_ai_answer_update_Handle, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + if (g_start_ai_answer_update_Handle != nullptr) + { + ret = osTimerDelete(g_start_ai_answer_update_Handle); + } + g_start_ai_answer_update_Handle = nullptr; + return; + } + return; + } + + void AiVoiceModel::stop_update_ai_answer_timer(void) + { + if (g_start_ai_answer_update_Handle != nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stop_update_ai_answer_timer"); + osTimerStop(g_start_ai_answer_update_Handle); + // 删除定时器并置为 nullptr + osStatus_t ret = osTimerDelete(g_start_ai_answer_update_Handle); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + } + g_start_ai_answer_update_Handle = nullptr; + START_UPDATE_AIANSWER_CNT = NUMBER_THREE; + } + } + + static osTimerId_t g_uapi_stop_tts_Handle = nullptr; + static void AI4G_UAPI_STOP_TTS_CallbackProc(int data) + { + AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer(); + } + + static void AI4G_UAPI_STOP_TTS_Callback(int data) + { + AI4G_UAPI_STOP_TTS_CallbackProc(data); + // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_UAPI_STOP_TTS_CallbackProc, data)); + } + + void AiVoiceModel::start_uapi_stop_tts_timer(uint32_t interval) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_uapi_stop_tts_timer"); + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_uapi_stop_tts_Handle != nullptr) + { + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!"); + return; + } + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_uapi_stop_tts_Handle = osTimerNew((osTimerFunc_t)AI4G_UAPI_STOP_TTS_Callback, osTimerPeriodic, nullptr, nullptr); + // 检查定时器创建是否成功 + if (g_uapi_stop_tts_Handle == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!"); + return; + } + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + /* --------------------------------- 4.启动定时器 -------------------------------- */ + osStatus_t ret = osTimerStart(g_uapi_stop_tts_Handle, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + if (g_uapi_stop_tts_Handle != nullptr) + { + ret = osTimerDelete(g_uapi_stop_tts_Handle); + } + g_uapi_stop_tts_Handle = nullptr; + return; + } + } + + void AiVoiceModel::stop_uapi_stop_tts_timer(void) + { + // 检查定时器是否存在 + if (g_uapi_stop_tts_Handle != nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stop_uapi_stop_tts_timer"); + osTimerStop(g_uapi_stop_tts_Handle); + // 删除定时器并置为 nullptr + osStatus_t ret = osTimerDelete(g_uapi_stop_tts_Handle); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + } + g_uapi_stop_tts_Handle = nullptr; + if (g_ai4g_is_start_tts_play_Handle == nullptr) + { + hasTtsStartSucceeded = false; +#if AI_VOICE_ENABLE + uapi_stop_tts(); +#endif + } + } + } + + // 设置选择的ai模型 + void AiVoiceModel::SetSelectAiModel(int index) + { +#if defined(AI_VOICE_N9) + ConfigModel::GetInstance()->SetSelectAiModel(0); +#else + ConfigModel::GetInstance()->SetSelectAiModel(index); +#endif + } + + int AiVoiceModel::GetSelectAiModel(void) + { + return ConfigModel::GetInstance()->GetSelectAiModel(); + } + + void AiVoiceModel::SetAI_4G_state(bool state) + { + AI_4G_state = state; + } + bool AiVoiceModel::GetAI_4G_state(void) + { + return AI_4G_state; + } + void AiVoiceModel::SetAI_BT_state(bool state) + { + AI_BT_state = state; + } + bool AiVoiceModel::GetAI_BT_state(void) + { + return AI_BT_state; + } + void AiVoiceModel::SetInit_4gai_task(bool state) + { + init_4gai_task = state; + } + bool AiVoiceModel::GetInit_4gai_task(void) + { + uint8_t asr_state = 0; + uint8_t chat_state = 0; + uint8_t tts_state = 0; +#if AI_VOICE_ENABLE + asr_state = get_ai_asr_service_init_flag(); + chat_state = get_ai_chat_service_init_flag(); + tts_state = get_ai_tts_server_init_flag(); +#endif + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "asr_state:%d,chat_state:%d,tts_state:%d", asr_state, chat_state, tts_state); + if ((asr_state == 1) && (chat_state == 1) && (tts_state == 1)) + { + init_4gai_task = true; + } + else + { + init_4gai_task = false; + } + return init_4gai_task; + } + + void AiVoiceModel::SetSelect4gorbt(int state) + { + select4gorbt = state; + } + int AiVoiceModel::GetSelect4gorbt(void) + { + return select4gorbt; + } + // 打断tts播放 + void AiVoiceModel::cancel_tts_play(void) + { +#if AI_VOICE_ENABLE + tts_server_deinit(); +#endif + } + + // 是否需要跳转到结果视图 + bool AiVoiceModel::is_need_to_jump_result_view(void) + { + if (userQuestionStr.empty()) + { + return false; + } + return true; + } + + bool AiVoiceModel::getentryTextViewState(void) + { + return entryTextViewState; + } + + bool AiVoiceModel::get_is_first_receive() + { + return isFirstReceive; + } + + void AiVoiceModel::set_is_first_receive(bool val) + { + isFirstReceive = val; + } + + // 删除开始的换行符 + void AiVoiceModel::delete_start_line_break_str(std::string &str) + { + if (GetSelect4gorbt() == AI_SELECT_4G && GetAiModelTextId() == STR_AIMODELS_DOUBAO) + { + if (isFirstReceive) + { + isFirstReceive = false; + // 检查是否以"\n\n"开头 + if (str.size() >= 2 && str[0] == '\n' && str[1] == '\n') + { + // 去除开头的两个换行符 + str = str.substr(2); + } + } + } + } + + /*获取已选择的ai模型的textid*/ + int AiVoiceModel::GetAiModelTextId() + { +#if 0 + int language = ConfigModel::GetInstance()->GetLanguage(); + int textId; + + if (language == 0) + { + selectAiModelToTextId = { + {0, {STR_AIMODES_WENXINYIYAN, 0}}, {1, {STR_AIMODES_KIMI, 2}}, {2, {STR_AIMODELS_DOUBAO, 3}}, // {3, {STR_TONGYI_QIANWEN, 4}}, {3, {STR_DEEPSEEK, 4}}, - // {4, {STR_IFLYTEK_SPARK, 5}}, - {4, {STR_AIMODES_LINGXI, 5}}, + {4, {STR_IFLYTEK_SPARK, 5}}, {5, {STR_AIMODES_CHATGPT, 1}}, }; textId = STR_AIMODES_WENXINYIYAN; @@ -1135,22 +1935,38 @@ namespace OHOS {3, {STR_AIMODELS_DOUBAO, 3}}, // {4, {STR_TONGYI_QIANWEN, 4}}, {4, {STR_DEEPSEEK, 4}}, - // {5, {STR_IFLYTEK_SPARK, 5}}, - {5, {STR_AIMODES_LINGXI, 5}}, + {5, {STR_IFLYTEK_SPARK, 5}}, }; textId = STR_AIMODES_CHATGPT; } - #endif - //客户新需求需要改模型顺序: +#endif +#ifdef AI_VOICE_JIUTIAN + int textId = 0; + selectAiModelToTextId = { + {0, {STR_DEEPSEEK, 4}}, + {1, {STR_JIUTIAN, 5}}, + {2, {STR_AIMODELS_DOUBAO, 3}}, + {3, {STR_AIMODES_WENXINYIYAN, 0}}, + {4, {STR_AIMODES_KIMI, 2}}, + {5, {STR_AIMODES_CHATGPT, 1}}, + }; + textId = STR_DEEPSEEK; +#elif defined(AI_VOICE_N9) + int textId = 0; + selectAiModelToTextId = { + {0, {STR_AIMODELS_DOUBAO, 3}}, + }; + textId = STR_AIMODELS_DOUBAO; +#else + // 客户新需求需要改模型顺序: int textId = 0; selectAiModelToTextId = { {0, {STR_DEEPSEEK, 4}}, - {1, {STR_AIMODES_CHATGPT, 1}}, + {1, {STR_JIUTIAN, 5}}, {2, {STR_AIMODELS_DOUBAO, 3}}, {3, {STR_AIMODES_WENXINYIYAN, 0}}, {4, {STR_AIMODES_KIMI, 2}}, - // {5, {STR_IFLYTEK_SPARK, 5}}, - {5, {STR_AIMODES_LINGXI, 5}}, + {5, {STR_AIMODES_CHATGPT, 1}}, }; textId = STR_DEEPSEEK; @@ -1160,8 +1976,41 @@ namespace OHOS { return it->second.first; } - +#endif return textId; } } + +#ifdef __cplusplus +#if __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +#endif /* __cplusplus */ + uint8_t getselect4gorbtai(void) // 获取AI模型选择的是4G还是蓝牙 + { + if (OHOS::AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G) + { + return 1; + } + return 0; + } + + static uint8_t clear_queue_stream = 0; + uint8_t get_clear_queue_stream(void) + { + return clear_queue_stream; + } + + // 清空队列中可能存在的音频数据 + void set_clear_queue_stream(uint8_t state) + { + clear_queue_stream = state; + } + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoicePresenter.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoicePresenter.cpp index 3b0418358..ab99d3cb0 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoicePresenter.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoicePresenter.cpp @@ -26,16 +26,49 @@ #include #include "gfx_utils/mem_check.h" - #include "player/include/PlayersModel.h" - #include "NativeRegisterManager.h" +#include "aivoice/include/AiVoiceSelectView.h" +#include "graphic_service.h" +#include "cat1_ws.h" namespace OHOS { REGIST_MENU_PRO(VIEW_AI_VOICE, AiVoiceView, AiVoicePresenter, - PNG_APPLIST_AIVOICE_IMAGE_BIG, PNG_APPLIST_AIVOICE_IMAGE,PNG_APPLIST_AIVOICE_IMAGE, "AI全家桶", STR_AI_FAMILY_MEALS); + PNG_APPLIST_AIVOICE_IMAGE_BIG, PNG_APPLIST_AIVOICE_IMAGE, PNG_APPLIST_AIVOICE_IMAGE, "AI全家桶", STR_AI_FAMILY_MEALS); + +#ifdef __cplusplus + extern "C" + { +#endif +#include "pm.h" +#include "pm_veto.h" +#include +#include +#include + extern void set_need_tts_reconnect(uint8_t flag); + + void remove_4GAI_vote(void) + { + uint8_t cnt = pm_veto_get_id_cnt(PM_ID_4G_AI); + if (cnt == 1) + { + uapi_pm_remove_sleep_veto(PM_ID_4G_AI); + } + } + + void add_4GAI_vote(void) + { + uint8_t cnt = pm_veto_get_id_cnt(PM_ID_4G_AI); + if (cnt == 0) + { + uapi_pm_add_sleep_veto(PM_ID_4G_AI); + } + } +#ifdef __cplusplus + } +#endif #define BLE_CONNECT_INTERVAL_HIGH_AI 10 // 当前Presenter属性实例化的内存指针 static AiVoicePresenter *g_pAiVoicePresenter = nullptr; @@ -70,33 +103,16 @@ namespace OHOS ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); // 开启一个60s取消长亮屏timer model->ai_start_screen60s_timer(); -#ifdef SUPPORT_BLE_SERVICE - uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH_AI); -#endif - } - - // 页面已经展示后的调用逻辑 - void AiVoicePresenter::OnResume(void) - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnResume"); - Presenter::OnResume(); - if (view_ == nullptr) - { - return; - } - } + add_4GAI_vote(); // 4g投票 - // 页面准备切换到后台前执行的逻辑 - void AiVoicePresenter::OnPause(void) - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnPause"); - Presenter::OnPause(); + uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH_AI); + Audio::AudioManager::GetInstance().SetVolume(AUDIO_STREAM_VOICE_ASSISTANT, 100); } // 页面完全置于后台时的逻辑。 void AiVoicePresenter::OnStop(void) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop"); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop start"); Presenter::OnStop(); ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); model->StatusResume(); @@ -104,25 +120,54 @@ namespace OHOS model->ai_stop_screen60s_timer(); model->stop_listening_timer(); model->stop_ai_isready_timer(); - #ifdef SUPPORT_BLE_SERVICE + model->stop_ai4g_connect_timer(); + model->stop_ai4g_tts_play_timer(); + model->stop_update_ai_answer_timer(); + model->stop_uapi_stop_tts_timer(); + remove_4GAI_vote(); // 移除4g投票 +#if AI_VOICE_ENABLE + dinit_ai_task(); + ai_cleanup_resources(); +#endif + uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_SLOW); - #endif + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop end"); + return; } /*调转到返回结果界面*/ bool AiVoicePresenter::JumpToReturnResultTextView(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView"); - if (view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID) != nullptr && - view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID)->IsVisible()) + if (model->GetSelect4gorbt() == AI_SELECT_4G) { preHeight = 0; - ChangeViewAndLogicOperator(AIVOICE_THINKING_VIEWID, AIVOICE_RETURN_RESULT_TEXT_VIEWID); + if (model->GetCurView() == AIVOICE_LISTENING_VIEWID || model->GetCurView() == AIVOICE_THINKING_VIEWID) + { + if (view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID) || view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID)) + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_RETURN_RESULT_TEXT_VIEWID); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView fail"); + return false; + } + } } - else + else if (model->GetSelect4gorbt() == AI_SELECT_BT) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView fail"); - return false; + if (view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID) != nullptr && + view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID)->IsVisible()) + { + preHeight = 0; + ChangeViewAndLogicOperator(AIVOICE_THINKING_VIEWID, AIVOICE_RETURN_RESULT_TEXT_VIEWID); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView fail"); + return false; + } } return true; } @@ -131,22 +176,42 @@ namespace OHOS bool AiVoicePresenter::ChangeToAIVoiceListeningView(bool val) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeToAIVoiceListeningView"); - if (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr && view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible()) + if (model->GetSelect4gorbt() == AI_SELECT_4G) { - model->stop_ai_isready_timer(); // 停止定时器 - if (val) /*如果查询的AI模型可用跳转到聆听中界面*/ + if (val) /*如果查询的AI模型可用跳转到聆听中界面*/ { - ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_LISTENING_VIEWID); + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_LISTENING_VIEWID); } else { - if(model->GetAiModelTextId() == STR_AIMODES_CHATGPT) //如果当前是在chatgpt模型*/ + if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/ { - ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ } else { - ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID); + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID); + } + } + } + else if (model->GetSelect4gorbt() == AI_SELECT_BT) + { + if (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr && view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible()) + { + if (val) /*如果查询的AI模型可用跳转到聆听中界面*/ + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_LISTENING_VIEWID); + } + else + { + if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/ + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ + } + else + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID); + } } } } @@ -175,7 +240,7 @@ namespace OHOS void AiVoicePresenter::FunctionKeyOnClickToChangeAIModel(void) { - if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) + if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) { int index = model->GetSelectAiModel() + 1; if (index >= AIMODES_MAX_NUM) @@ -193,12 +258,12 @@ namespace OHOS // 右滑切换模型 void AiVoicePresenter::DragLeftToRightChangeAIModel(void) { - if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) + if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) { - int index = model->GetSelectAiModel() + 1; - if (index >= AIMODES_MAX_NUM) + int index = model->GetSelectAiModel() - 1; + if (index < 0) { - index = 0; + index = AIMODES_CHATGPT; } WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiModelsPresenter::index = %d", index); model->SetSelectAiModel(index); @@ -210,12 +275,12 @@ namespace OHOS // 左滑切换模型 void AiVoicePresenter::DragRightToLetfChangeAIModel(void) { - if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) + if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) { - int index = model->GetSelectAiModel() - 1; - if (index < 0) + int index = model->GetSelectAiModel() + 1; + if (index >= AIMODES_MAX_NUM) { - index = AIMODES_CHATGPT; + index = 0; } WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiModelsPresenter::index = %d", index); model->SetSelectAiModel(index); @@ -226,8 +291,17 @@ namespace OHOS bool AiVoicePresenter::ChangeViewAndLogicOperator(int16_t hideView, int16_t showView) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeViewOperator"); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeViewOperator"); + + // 加锁,作用域结束时自动释放锁 + // std::lock_guard lock(m_mutex); + bool isSameView = (hideView == showView); + if (isSameView) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Same view no need to change"); + return false; + } if (hideView > MAX_AIVOICE_VIEWID) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Overstep ones bounds"); @@ -242,31 +316,15 @@ namespace OHOS switch (hideView) { case AIVOICE_STARTCHAT_VIEWID: - model->QuerySelectedAiModelIsConnect(); /*查询用户选择的AI模型是否已经连接*/ - if (showView == AIVOICE_LISTENING_VIEWID) - { - model->StartListenAndRecordingUserQuestion(); - } - else if (showView == AIVOICE_AIMODE_CONNECTING) - { - model->start_ai_isready_timer(); /*开启一个查询AI模型是否连接成功定时器*/ - } break; case AIVOICE_AIMODE_CONNECTING: - if (showView == AIVOICE_LISTENING_VIEWID) - { - model->StartListenAndRecordingUserQuestion(); - } + model->stop_ai_isready_timer(); // 停止定时器 break; case AIVOICE_LISTENING_VIEWID: model->StopListenAndRecordingUserQuestion(); model->stop_listening_timer(); - if (showView == AIVOICE_THINKING_VIEWID) // 聆听中->思考中界面 - { - model->AIVoice_StartTimer(); - } break; case AIVOICE_THINKING_VIEWID: @@ -274,23 +332,59 @@ namespace OHOS break; case AIVOICE_RETURN_RESULT_TEXT_VIEWID: + // set_need_tts_reconnect(0); // 停止tts重连 AiVoiceModel::GetInstance().ClearQuestionAndAiAnswerStr(); // 清空上次用户问题和Ai回答字符串 AiVoiceModel::GetInstance().SetIsClickable(false); AiVoiceModel::GetInstance().SetIsLimitDisplayed(false); - if (showView == AIVOICE_LISTENING_VIEWID) - { - model->StartListenAndRecordingUserQuestion(); - } + AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer(); + AiVoiceModel::GetInstance().stop_update_ai_answer_timer(); + AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer(); break; + case AIVOICE_4GSERVICECON_VIEW: + model->stop_ai4g_connect_timer(); + break; default: // Handle other cases if needed break; } + switch (showView) + { + case AIVOICE_AIMODE_CONNECTING: + model->QuerySelectedAiModelIsConnect(); + AiVoiceModel::GetInstance().start_ai_isready_timer(); + break; + case AIVOICE_RETURN_RESULT_TEXT_VIEWID: + // set_need_tts_reconnect(1); // 开始tts重连 + break; + case AIVOICE_LISTENING_VIEWID: + // set_stop_send_ai_flag(0); // 开始发送AI数据 + AiVoiceModel::GetInstance().StartListenAndRecordingUserQuestion(); + AiVoiceModel::GetInstance().start_listening_timer(); + break; + + case AIVOICE_THINKING_VIEWID: + AiVoiceModel::GetInstance().AIVoice_StartTimer(); + break; + + default: + break; + } + return true; } + void AiVoicePresenter::JumpThinkingView(void) + { + if ((view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID) != nullptr) && + (view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID)->IsVisible())) + { + ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); + } + return; + } + // 处理手点击屏幕切换AI模型 bool AiVoicePresenter::OnClick(UIView &view, const ClickEvent &event) { @@ -314,56 +408,14 @@ namespace OHOS return true; } - bool AiVoicePresenter::OnPress(UIView& view, const PressEvent& event) + bool AiVoicePresenter::OnPress(UIView &view, const PressEvent &event) { UNUSED(event); std::string viewId = view.GetViewId(); - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRelease %s", viewId.c_str()); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnPress %s", viewId.c_str()); /* ----------------------------- 重置60s取消常亮屏timer ---------------------------- */ model->reset_ai_screen60s_timer_time(); /* -------------------------------------------------------------------------- */ - std::unordered_map> viewIdMap = { - {AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面,并清除手表聊天记录 - {AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_LISTENING_VIEWID}}, // 返回继续聆听,并清除手表聊天记录 - }; - auto it = viewIdMap.find(viewId); - if (it != viewIdMap.end()) - { - #if 0 - if(!model->GetIsClickable()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "当前还不可点击"); - return true; - } - #endif - if (it->first == AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID) // 点击继续对话按钮要发取消当前对话指令,避免AI回应中途按继续对话按钮没有取消上一次对话问题 - { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CancelCurAIChat"); - AiVoiceModel::GetInstance().CancelCurAIChat(); - // AiVoiceModel::GetInstance().sendAIIsReady(); - PlayersModel::GetInstance()->HandPausePhoneMusic(); // 暂停手机音乐 - PlayersModel::GetInstance()->PlayerPause(); // 暂停手机音乐 - } - ChangeViewAndLogicOperator(it->second.first, it->second.second); - return true; - } - return true; - } - - bool AiVoicePresenter::OnRelease(UIView &view, const ReleaseEvent &event) - { - UNUSED(event); - std::string viewId = view.GetViewId(); - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRelease %s", viewId.c_str()); - /* ----------------------------- 重置60s取消常亮屏timer ---------------------------- */ - model->reset_ai_screen60s_timer_time(); - /* -------------------------------------------------------------------------- */ - - // if ((viewId == AIVOICE_CHAT_BUTTON_VIEW_ID) && model->IsExistOpenAIAPIKeys() == false) // 如果点击的是(对话按钮)且未配置apikey - // { - // ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ - // return true; - // } if (viewId == AIVOICE_APIKEYS_BUTTON_VIEW_ID) // 如果点击的是API Keys按钮(注:暂时不用) { if (model->IsExistOpenAIAPIKeys() == true) @@ -391,53 +443,202 @@ namespace OHOS bool appBluetoothConnectState = model->GetAPPBluetoothIsConnect(); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "netWork4GState = %d,appBluetoothConnectState = %d", netWork4GState, appBluetoothConnectState); - if (netWork4GState) // 1.手表4G网络正常 + model->SetAI_4G_state(netWork4GState); + model->SetAI_BT_state(appBluetoothConnectState); + if ((netWork4GState && appBluetoothConnectState)) + { + // 获取用户上次的选择 + int lastSelectedType = model->GetSelect4gorbt(); + // 两者都可用,检查是否有上次的选择 + if (lastSelectedType == AI_SELECT_4G) + { + // 使用4G + model->SetSelect4gorbt(AI_SELECT_4G); + if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/ + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ + return true; + } + if (!model->GetInit_4gai_task()) + { + // init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType()); + model->start_ai4g_connect_timer(); + ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_4GSERVICECON_VIEW); // LOADING + } + else + { + ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING + } + } + else if (lastSelectedType == AI_SELECT_BT) + { + // 使用蓝牙 + model->SetSelect4gorbt(AI_SELECT_BT); + ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING + } + else + { + // 没有上次的选择,让用户选择 + ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_SELECT_VIEW); // LOADING + } + } + else if (netWork4GState) // 1.手表4G网络正常 { // 通过4G调用大模型 + model->SetSelect4gorbt(AI_SELECT_4G); + if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/ + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ + return true; + } + if (!model->GetInit_4gai_task()) + { + // init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType()); + model->start_ai4g_connect_timer(); + ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_4GSERVICECON_VIEW); // LOADING + } + else + { + ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING + } } else if (appBluetoothConnectState) // 3.只有与APP蓝牙连接正常 { // 通过蓝牙连接APP调用大模型 + model->SetSelect4gorbt(AI_SELECT_BT); ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING } else // 4.两者连接都异常 { // 返回错误 + model->SetSelect4gorbt(AI_SELECT_DEFAULT); ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID); - // ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID); } return true; } else if (viewId == FINISH_SPEAKING_BUTTON_VIEW_ID) // 如果点击的是说话完毕按钮 { - ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); + if (model->GetSelect4gorbt() == AI_SELECT_4G) + { +#if AI_VOICE_ENABLE + uapi_UI_stop_asr(); +#endif + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "FINISH_SPEAKING_BUTTON_VIEW_ID:(%d,%d)", model->is_need_to_jump_result_view(), model->getentryTextViewState()); + if (!model->is_need_to_jump_result_view() && !model->getentryTextViewState()) // 没有数据就跳转到思考中界面 + { + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&OHOS::AiVoicePresenter::JumpThinkingView, OHOS::AiVoicePresenter::GetInstance())); + } + } + else if (model->GetSelect4gorbt() == AI_SELECT_BT) + { + ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); + } + return true; + } + else if (viewId == AIVOICE_SELECT_VIEW_BUTTON4G_VIEW_ID) // 如果点击的是4G连接方式 + { + // 通过4G调用大模型 + model->SetSelect4gorbt(AI_SELECT_4G); + if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/ + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/ + return true; + } + if (!model->GetInit_4gai_task()) + { + // init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType()); + model->start_ai4g_connect_timer(); + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_4GSERVICECON_VIEW); // LOADING + } + else + { + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODE_CONNECTING); // LOADING + } + return true; + } + else if (viewId == AIVOICE_SELECT_VIEW_BUTTONBT_VIEW_ID) // 如果点击的是蓝牙连接方式 + { + model->SetSelect4gorbt(AI_SELECT_BT); + ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODE_CONNECTING); return true; } std::unordered_map> viewIdMap = { + {AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面,并清除手表聊天记录 + {AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_LISTENING_VIEWID}}, // 返回继续聆听,并清除手表聊天记录 + }; + auto it = viewIdMap.find(viewId); + if (it != viewIdMap.end()) + { + if (it->first == AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID) // 点击继续对话按钮要发取消当前对话指令,避免AI回应中途按继续对话按钮没有取消上一次对话问题 + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CancelCurAIChat"); + PlayersModel::GetInstance()->HandPausePhoneMusic(); // 暂停手机音乐 + PlayersModel::GetInstance()->PlayerPause(); // 暂停手机音乐 + if (model->GetSelect4gorbt() == AI_SELECT_4G) + { + AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer(); + AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer(); + // usleep(50000); + set_clear_queue_stream(1); + LOS_Msleep(100); + // uapi_UI_start_asr(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType()); + ChangeViewAndLogicOperator(AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_AIMODE_CONNECTING); + return true; + } + else if (model->GetSelect4gorbt() == AI_SELECT_BT) + { + AiVoiceModel::GetInstance().CancelCurAIChat(); + AiVoiceModel::GetInstance().sendAIIsReady(); + } + } + else if (it->first == AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID) + { + if (model->GetSelect4gorbt() == AI_SELECT_4G) + { + AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer(); + AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer(); + set_clear_queue_stream(1); + LOS_Msleep(100); +#if AI_VOICE_ENABLE + dinit_ai_task(); +#endif + } + } + ChangeViewAndLogicOperator(it->second.first, it->second.second); + return true; + } + + std::unordered_map> viewIdMap2 = { {ALERT_APPBLUETOOTH_AND_4GNETWORK_ENSURE_BUTTON_VIEW_ID, {AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面 {AIMODEL_CONNECT_FAILED_ENSURE_BUTTON_VIEW_ID, {AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面 {AIVOICECONNECTTIMEOUT_ENSURE_BUTTON_VIEW_ID, {AIVOICE_CONNECT_TIMEOUT_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面 {CANCEL_THINKING_BUTTON_VIEW_ID, {AIVOICE_THINKING_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面 {AIVOICECONNECTINGVIEW_CANCEL_BUTTON_VIEW_ID, {AIVOICE_AIMODE_CONNECTING, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面 - // {AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面,并清除手表聊天记录 - // {AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_LISTENING_VIEWID}}, // 返回继续聆听,并清除手表聊天记录 }; - auto it = viewIdMap.find(viewId); - if (it != viewIdMap.end()) + it = viewIdMap2.find(viewId); + if (it != viewIdMap2.end()) { - // if (it->first == AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID) // 点击继续对话按钮要发取消当前对话指令,避免AI回应中途按继续对话按钮没有取消上一次对话问题 - // { - // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CancelCurAIChat"); - // AiVoiceModel::GetInstance().CancelCurAIChat(); - // PlayersModel::GetInstance()->HandPausePhoneMusic(); // 暂停手机音乐 - // PlayersModel::GetInstance()->PlayerPause(); // 暂停手机音乐 - // } + if (it->first != ALERT_APPBLUETOOTH_AND_4GNETWORK_ENSURE_BUTTON_VIEW_ID) + { + if (model->GetSelect4gorbt() == AI_SELECT_4G) + { +#if AI_VOICE_ENABLE + dinit_ai_task(); +#endif + LOS_Msleep(50); + } + } ChangeViewAndLogicOperator(it->second.first, it->second.second); return true; } return true; } + bool AiVoicePresenter::OnRelease(UIView &view, const ReleaseEvent &event) + { + return true; + } bool AiVoicePresenter::OnDrag(UIView &view, const DragEvent &event) { @@ -471,7 +672,7 @@ namespace OHOS if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)) { /*AI对话界面右滑退出当前Slice*/ - // NativeAbility::GetInstance().Back(); + // NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS); DragLeftToRightChangeAIModel(); } else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID)) @@ -486,11 +687,19 @@ namespace OHOS } else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID)) { + if (model->GetSelect4gorbt() == AI_SELECT_4G) + { + return true; + } /*聆听中界面右滑退回到AI对话界面*/ ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_STARTCHAT_VIEWID); } else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID)) { + if (model->GetSelect4gorbt() == AI_SELECT_4G) + { + return true; + } /*思考中界面右滑退到AI对话界面*/ ChangeViewAndLogicOperator(AIVOICE_THINKING_VIEWID, AIVOICE_STARTCHAT_VIEWID); } @@ -504,6 +713,16 @@ namespace OHOS /*连接超时界面右滑退到AI对话界面*/ ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_STARTCHAT_VIEWID); } + else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_SELECT_VIEW)) + { + /*连接超时界面右滑退到AI对话界面*/ + ChangeViewAndLogicOperator(AIVOICE_SELECT_VIEW, AIVOICE_STARTCHAT_VIEWID); + } + else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_VOLUME_VIEW)) + { + /*连接超时界面右滑退到AI对话界面*/ + ChangeViewAndLogicOperator(AIVOICE_VOLUME_VIEW, AIVOICE_STARTCHAT_VIEWID); + } AiVoicePresenter::X_DRAG_FLAG = false; } else if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT && event.GetDragDirection() == DragEvent::DIRECTION_BOTTOM_TO_TOP) /*上滑*/ @@ -531,7 +750,10 @@ namespace OHOS if (keyID == static_cast(ZliteKeyCode::ZLITE_KEY_POWER) && keyState == 1 && uapi_get_screen_state() == 0) { NativeAbility::GetInstance().Back(); - AiVoiceModel::GetInstance().CancelCurAIChat(); + if (model->GetSelect4gorbt() == AI_SELECT_BT) + { + AiVoiceModel::GetInstance().CancelCurAIChat(); + } } return true; } @@ -539,7 +761,7 @@ namespace OHOS void AiVoicePresenter::OnPickerStoped(UIPicker &picker) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnPickerStoped,%d", picker.GetSelected()); - if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) + if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) { model->SetSelectAiModel(picker.GetSelected()); view_->ChangeAiModelAndUpdateComponentsStatus(); @@ -565,23 +787,88 @@ namespace OHOS { preHeight = label.GetTextHeight(); isScroll = true; + if ((view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) != nullptr) && + (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible())) + { + if (isScroll) + { + // 监听,让List实现滚动 + AivoiceReturnResultTextView::GetInstance()->GetChatContentList()->ScrollBy(-120); + isScroll = false; + } + } } return; } - //监听高度是否变化 - void AiVoicePresenter::Notify() + void AiVoicePresenter::ChangeVolume(UIView &view, const RotateEvent &event) { if ((view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) != nullptr) && (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible())) { - if (isScroll) + UISlider *slider = dynamic_cast(&view); + if (slider) { - // 监听,让List实现滚动 - AivoiceReturnResultTextView::GetInstance()->GetChatContentList()->ScrollBy(-120); - isScroll = false; + int value = slider->GetValue(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "volume:%d front", value); + if (event.GetRotate() <= 0) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "222"); + value += 20; + if (value > 100) + { + value = 100; + } + } + else + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "111"); + value -= 20; + if (value < 0) + { + value = 0; + } + } + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "volume:%d end", value); + do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_CHANGE_SYSTEM_VOLUME, (void *)(&value), sizeof(value)); } } - return; + } + + bool AiVoicePresenter::OnRotate(UIView &view, const RotateEvent &event) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate"); + static uint32_t lastCallTime = 0; + const uint32_t MIN_INTERVAL = 500; // 最小间隔500ms + + uint32_t currentTime = event.GetTimeStamp(); + + // 计算时间间隔 + uint32_t interval = currentTime - lastCallTime; + + // 仅当间隔大于500ms时才调用ChangeVolume + if (interval >= MIN_INTERVAL) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate: 允许调用ChangeVolume, 间隔: %ums", interval); + ChangeVolume(view, event); + lastCallTime = currentTime; + } + else + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate: 忽略调用ChangeVolume, 间隔: %ums (需要>500ms)", interval); + } + + return true; + } + + bool AiVoicePresenter::OnRotateEnd(UIView &view, const RotateEvent &event) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotateEnd"); + // if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true) + // { + // ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_VOLUME_VIEW); + // } + ChangeVolume(view, event); + return true; } } \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp new file mode 100644 index 000000000..934c24202 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp @@ -0,0 +1,175 @@ +#include "aivoice/include/AiVoicePresenter.h" +#include "aivoice/include/AiVoiceSelectView.h" +#include "wearable_log.h" + +namespace OHOS +{ + static AiVoiceSelectView *g_pAivoiceSelectView{nullptr}; + AiVoiceSelectView::AiVoiceSelectView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::AiVoiceSelectView"); + g_pAivoiceSelectView = this; + } + AiVoiceSelectView::~AiVoiceSelectView() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::~AiVoiceSelectView"); + ClearAll(); + g_pAivoiceSelectView = nullptr; + } + + AiVoiceSelectView *AiVoiceSelectView::GetInstance(void) + { + return g_pAivoiceSelectView; + } + + void AiVoiceSelectView::ClearAll(void) + { + if (scrollView != nullptr) + { + scrollView->RemoveAll(); + delete title; + title = nullptr; + delete label4g; + label4g = nullptr; + delete labelbt; + labelbt = nullptr; + delete button4g; + button4g = nullptr; + delete buttonbt; + buttonbt = nullptr; + delete scrollView; + scrollView = nullptr; + } + } + + UIScrollView *AiVoiceSelectView::CreateAiVoiceSelectView(void) + { + if (scrollView == nullptr) + { + scrollView = new UIScrollView(); + if (scrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::scrollView new fail!"); + return nullptr; + } + } + scrollView->SetPosition(0, 0, 466, 466); + UIView::OnDragListener *dragListener = static_cast(AiVoicePresenter::GetInstance()); + if (dragListener == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::dragListener new fail!"); + return nullptr; + } + scrollView->SetOnDragListener(dragListener); + scrollView->SetTouchable(true); + scrollView->SetDraggable(true); + /* -------------------------------------------------------------------------- */ + if (title == nullptr) + { + title = new UILabelExt(); + if (title == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!"); + return nullptr; + } + } + title->SetPosition(83, 50, 300, 35); + title->SetStyle(STYLE_TEXT_FONT, 30); + title->SetStyle(STYLE_LINE_HEIGHT, 35); + title->SetText("AI对话"); + title->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + title->SetRollSpeed(23); + title->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + title->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + scrollView->Add(title); + /* -------------------------------------------------------------------------- */ + int y1 = 123; + if (label4g == nullptr) + { + label4g = new UILabelExt(); + if (label4g == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!"); + return nullptr; + } + } + label4g->SetPosition(83, y1 + 33, 300, 35); + label4g->SetStyle(STYLE_TEXT_FONT, 30); + label4g->SetStyle(STYLE_LINE_HEIGHT, 35); + label4g->SetText("4G连接"); + label4g->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + label4g->SetRollSpeed(23); + label4g->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + label4g->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* -------------------------------------------------------------------------- */ + int y2 = 243; + if (labelbt == nullptr) + { + labelbt = new UILabelExt(); + if (labelbt == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!"); + return nullptr; + } + } + labelbt->SetPosition(83, y2 + 33, 300, 35); + labelbt->SetStyle(STYLE_TEXT_FONT, 30); + labelbt->SetStyle(STYLE_LINE_HEIGHT, 35); + labelbt->SetText("蓝牙连接"); + labelbt->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + labelbt->SetRollSpeed(23); + labelbt->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); + labelbt->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); + /* -------------------------------------------------------------------------- */ + if (button4g == nullptr) + { + button4g = new UIButton(); + if (button4g == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!"); + return nullptr; + } + } + button4g->SetPosition(43, 123, 380, 100); + button4g->SetViewId(AIVOICE_SELECT_VIEW_BUTTON4G_VIEW_ID); + button4g->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); + button4g->SetStyle(STYLE_BACKGROUND_OPA, 0xff); + button4g->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED); + UIView::OnTouchListener *listener4g = static_cast(AiVoicePresenter::GetInstance()); + if (listener4g == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::listener4g new fail!"); + return nullptr; + } + button4g->SetOnTouchListener(listener4g); + /* -------------------------------------------------------------------------- */ + if (buttonbt == nullptr) + { + buttonbt = new UIButton(); + if (buttonbt == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!"); + return nullptr; + } + } + buttonbt->SetPosition(43, 243, 380, 100); + buttonbt->SetViewId(AIVOICE_SELECT_VIEW_BUTTONBT_VIEW_ID); + buttonbt->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); + buttonbt->SetStyle(STYLE_BACKGROUND_OPA, 0xff); + buttonbt->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED); + UIView::OnTouchListener *listenerbt = static_cast(AiVoicePresenter::GetInstance()); + if (listenerbt == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::listenerbt new fail!"); + return nullptr; + } + buttonbt->SetOnTouchListener(listenerbt); + + scrollView->Add(button4g); + scrollView->Add(buttonbt); + scrollView->Add(label4g); + scrollView->Add(labelbt); + + return scrollView; + } +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceView.cpp index 5ee1d2840..bcf2d91ec 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceView.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceView.cpp @@ -34,112 +34,136 @@ namespace OHOS return g_pAiVoiceView; } - void AiVoiceView::ClearAll(void) + void AiVoiceView::ClearAllAiVoiceScrollView(void) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ClearAll"); - if (viewInitStatus) + if (scrollView != nullptr) { - + scrollView->RemoveAll(); + delete scrollView; + scrollView = nullptr; - if (AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] != nullptr) - { - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->RemoveAll(); + delete VolumeProcess; + VolumeProcess = nullptr; - delete title; - title = nullptr; + delete title; + title = nullptr; - delete aiModelImage; - aiModelImage = nullptr; + delete aiModelImage; + aiModelImage = nullptr; - delete startChatButton; - startChatButton = nullptr; + delete startChatButton; + startChatButton = nullptr; - delete startChatLabel; - startChatLabel = nullptr; + delete startChatLabel; + startChatLabel = nullptr; - delete chatButton; - chatButton = nullptr; + delete chatButton; + chatButton = nullptr; - delete chatLabel; - chatLabel = nullptr; + delete chatLabel; + chatLabel = nullptr; - delete apiKeysLabel; - apiKeysLabel = nullptr; + delete apiKeysLabel; + apiKeysLabel = nullptr; - delete apiKeysButton; - apiKeysButton = nullptr; + delete apiKeysButton; + apiKeysButton = nullptr; - delete aiModelPicker; - aiModelPicker = nullptr; + delete aiModelPicker; + aiModelPicker = nullptr; - delete buttonBgImage; - buttonBgImage = nullptr; + delete buttonBgImage; + buttonBgImage = nullptr; - delete upImage; - upImage = nullptr; + delete upImage; + upImage = nullptr; + } + } - delete AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]; - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] = nullptr; - } + void AiVoiceView::ClearAll(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ClearAll"); + ClearAllAiVoiceScrollView(); - if (p_AiVoiceBluetoothFailedStartView != nullptr) - { - delete p_AiVoiceBluetoothFailedStartView; - p_AiVoiceBluetoothFailedStartView = nullptr; - } + if (p_AiVoiceBluetoothFailedStartView != nullptr) + { + delete p_AiVoiceBluetoothFailedStartView; + p_AiVoiceBluetoothFailedStartView = nullptr; + } - if (p_AivoiceMobileDataFailedStartView != nullptr) - { - delete p_AivoiceMobileDataFailedStartView; - p_AivoiceMobileDataFailedStartView = nullptr; - } + if (p_AivoiceMobileDataFailedStartView != nullptr) + { + delete p_AivoiceMobileDataFailedStartView; + p_AivoiceMobileDataFailedStartView = nullptr; + } - if (p_AivoiceConnectTimeoutView != nullptr) - { - delete p_AivoiceConnectTimeoutView; - p_AivoiceConnectTimeoutView = nullptr; - } + if (p_AivoiceConnectTimeoutView != nullptr) + { + delete p_AivoiceConnectTimeoutView; + p_AivoiceConnectTimeoutView = nullptr; + } - if (p_AivoiceListeningView != nullptr) - { - delete p_AivoiceListeningView; - p_AivoiceListeningView = nullptr; - } + if (p_AivoiceListeningView != nullptr) + { + delete p_AivoiceListeningView; + p_AivoiceListeningView = nullptr; + } - if (p_AivoiceThinkingView != nullptr) - { - delete p_AivoiceThinkingView; - p_AivoiceThinkingView = nullptr; - } + if (p_AivoiceThinkingView != nullptr) + { + delete p_AivoiceThinkingView; + p_AivoiceThinkingView = nullptr; + } - if (p_AivoiceReturnResultTextView != nullptr) - { - delete p_AivoiceReturnResultTextView; - p_AivoiceReturnResultTextView = nullptr; - } + if (p_AivoiceReturnResultTextView != nullptr) + { + delete p_AivoiceReturnResultTextView; + p_AivoiceReturnResultTextView = nullptr; + } - if (p_SetApiKeysView != nullptr) - { - delete p_SetApiKeysView; - p_SetApiKeysView = nullptr; - } + if (p_SetApiKeysView != nullptr) + { + delete p_SetApiKeysView; + p_SetApiKeysView = nullptr; + } - if (p_NotSetApiKeysView != nullptr) - { - delete p_NotSetApiKeysView; - p_NotSetApiKeysView = nullptr; - } + if (p_NotSetApiKeysView != nullptr) + { + delete p_NotSetApiKeysView; + p_NotSetApiKeysView = nullptr; + } - if (p_ApiKeysDeleteView != nullptr) - { - delete p_ApiKeysDeleteView; - p_ApiKeysDeleteView = nullptr; - } + if (p_ApiKeysDeleteView != nullptr) + { + delete p_ApiKeysDeleteView; + p_ApiKeysDeleteView = nullptr; + } - if (p_AiVoiceConnectingView != nullptr) + if (p_AiVoiceConnectingView != nullptr) + { + delete p_AiVoiceConnectingView; + p_AiVoiceConnectingView = nullptr; + } + if (p_AiVoiceSelectView != nullptr) + { + delete p_AiVoiceSelectView; + p_AiVoiceSelectView = nullptr; + } + if (p_Aivoice4gServiceConView != nullptr) + { + delete p_Aivoice4gServiceConView; + p_Aivoice4gServiceConView = nullptr; + } + if (p_AiVoiceVolumeView) + { + delete p_AiVoiceVolumeView; + p_AiVoiceVolumeView = nullptr; + } + for (int i = 0; i < MAX_AIVOICE_VIEWID; i++) + { + if (AiVoiceScrollView[i] != nullptr) { - delete p_AiVoiceConnectingView; - p_AiVoiceConnectingView = nullptr; + AiVoiceScrollView[i] = nullptr; } } } @@ -402,8 +426,11 @@ namespace OHOS aiModelPicker->SetStyle(STYLE_BORDER_RADIUS, 150); aiModelPicker->SetItemHeight(40); aiModelPicker->SetLoopState(true); +#if defined(AI_VOICE_FD230) || defined(AI_VOICE_N9) +#else aiModelPicker->SetRotateFactor(1.0); aiModelPicker->RequestFocus(); +#endif aiModelPicker->RegisterSelectedListener(presenter_); // 设置文本颜色为透明 aiModelPicker->SetTextColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0x00), Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0x00)); @@ -418,53 +445,86 @@ namespace OHOS bool AiVoiceView::CreateAiVoiceScrollView(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceScrollView"); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] = new UIScrollView(); - if (AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] == nullptr) + if (scrollView == nullptr) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] new fail!"); - return false; + scrollView = new UIScrollView(); + if (scrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] new fail!"); + return false; + } } - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetPosition(0, 0, 466, 466); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetTouchable(true); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetDraggable(true); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetOnDragListener(presenter_); - AddViewToRootContainer(AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]); + scrollView->SetPosition(0, 0, 466, 466); + scrollView->SetHorizontalScrollState(false); + scrollView->SetVerticalScrollState(false); + scrollView->SetTouchable(true); + scrollView->SetDraggable(true); + scrollView->SetOnDragListener(presenter_); + return true; + } + bool AiVoiceView::CreateAiVoiceVoiceView(void) + { + /* ------------------------------ VolumeProcess ----------------------------- */ + if (VolumeProcess == nullptr) + { + VolumeProcess = new UISlider(); + if (VolumeProcess == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "VolumeProcess new fail"); + return false; + } + VolumeProcess->SetSliderColor(Color::Gray(), Color::Silver()); + VolumeProcess->SetPosition(-200, 77, 130, 310); + VolumeProcess->SetDirection(UISlider::Direction::DIR_BOTTOM_TO_TOP); + VolumeProcess->SetRange(100, 0); + VolumeProcess->SetStyle(STYLE_BORDER_RADIUS, 100); + VolumeProcess->SetBackgroundStyle(STYLE_LINE_CAP, CapType::CAP_ROUND); + VolumeProcess->SetForegroundStyle(STYLE_LINE_CAP, CapType::CAP_ROUND); + VolumeProcess->SetSliderColor(Color::GetColorFromRGBA(0x19, 0x19, 0x19, 0xff), Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff)); + VolumeProcess->SetForegroundStyle(STYLE_BACKGROUND_OPA, 0xff); + VolumeProcess->SetKnobStyle(StyleDefault::GetSliderKnobStyle()); + VolumeProcess->RequestFocus(); + VolumeProcess->SetRotateFactor(5.0); + // VolumeProcess->SetVisible(false); + VolumeProcess->SetOnRotateListener(presenter_); + AddViewToRootContainer(VolumeProcess); + } return true; } - void AiVoiceView::CreateAiVoiceView(void) + UIScrollView *AiVoiceView::CreateAiVoiceView(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceView"); if (!CreateAiVoiceScrollView() || !CreateAiVoiceViewImageView() || !CreateAiVoiceViewPicker() || - !CreateAiVoiceViewLabel() || !CreateAiVoiceViewButton()) + !CreateAiVoiceViewLabel() || !CreateAiVoiceViewButton() || !CreateAiVoiceVoiceView()) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceView fail!"); - return; + return nullptr; } - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(title); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(aiModelPicker); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(aiModelImage); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(startChatButton); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(startChatLabel); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(chatButton); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(chatLabel); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(apiKeysButton); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(apiKeysLabel); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(buttonBgImage); - AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(upImage); + // scrollView->Add(VolumeProcess); + scrollView->Add(title); + scrollView->Add(aiModelPicker); + scrollView->Add(aiModelImage); + scrollView->Add(startChatButton); + scrollView->Add(startChatLabel); + scrollView->Add(chatButton); + scrollView->Add(chatLabel); + scrollView->Add(apiKeysButton); + scrollView->Add(apiKeysLabel); + scrollView->Add(buttonBgImage); + scrollView->Add(upImage); + + return scrollView; } void AiVoiceView::OnStart() { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::OnStart"); - - - if (!viewInitStatus) - { - CreateAiVoiceView(); - viewInitStatus = true; - } + ChangeView(MAX_AIVOICE_VIEWID, AIVOICE_STARTCHAT_VIEWID); +#if defined(AI_VOICE_FD230) || defined(AI_VOICE_N9) + CreateAiVoiceVoiceView(); +#endif SetAiVoiceViewAllComponentsVisibilityStatus(); @@ -480,9 +540,26 @@ namespace OHOS WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoiceStartChatView"); if (AiVoiceScrollView[thisView] == nullptr) { + UIScrollView *scrollview = CreateAiVoiceView(); + if (scrollview == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + AiVoiceScrollView[thisView] = scrollview; AddViewToRootContainer(AiVoiceScrollView[thisView]); } - AiVoiceModel::GetInstance().CancelCurAIChat(); + else + { + if (VolumeProcess) + { + VolumeProcess->RequestFocus(); + } + } + if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT) + { + AiVoiceModel::GetInstance().CancelCurAIChat(); + } return true; } @@ -586,10 +663,10 @@ namespace OHOS } if (p_AivoiceListeningView) { + p_AivoiceListeningView->StartOrStopAivoiceListeningImageAnimatorView(true); p_AivoiceListeningView->GetShowtimeoutLabel()->SetText("10"); p_AivoiceListeningView->GetShowtimeoutLabel()->Invalidate(); } - AiVoiceModel::GetInstance().start_listening_timer(); return true; } @@ -615,6 +692,10 @@ namespace OHOS AiVoiceScrollView[thisView] = scrollview; AddViewToRootContainer(AiVoiceScrollView[thisView]); } + if (p_AivoiceThinkingView) + { + p_AivoiceThinkingView->StartOrStopAiVoiceThinkingImageAnimatorView(true); + } return true; } @@ -624,6 +705,7 @@ namespace OHOS WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoicReturnResultTextView"); if (AiVoiceScrollView[thisView] == nullptr) { + AiVoiceModel::GetInstance().SetChatContentListCount(0); p_AivoiceReturnResultTextView = new AivoiceReturnResultTextView(); if (p_AivoiceReturnResultTextView == nullptr) { @@ -743,6 +825,75 @@ namespace OHOS return true; } + bool AiVoiceView::ChangeAiVoicSelectView(int16_t thisView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoicSelectView"); + if (AiVoiceScrollView[thisView] == nullptr) + { + p_AiVoiceSelectView = new AiVoiceSelectView(); + if (p_AiVoiceSelectView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + UIScrollView *scrollview = p_AiVoiceSelectView->CreateAiVoiceSelectView(); + if (scrollview == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + AiVoiceScrollView[thisView] = scrollview; + AddViewToRootContainer(AiVoiceScrollView[thisView]); + } + return true; + } + + bool AiVoiceView::ChangeAiVoic4gServiceConView(int16_t thisView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoic4gServiceConView"); + if (AiVoiceScrollView[thisView] == nullptr) + { + p_Aivoice4gServiceConView = new AiVoice4gServiceConView(); + if (p_Aivoice4gServiceConView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + UIScrollView *scrollview = p_Aivoice4gServiceConView->CreateAiVoice4gServiceConView(); + if (scrollview == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + AiVoiceScrollView[thisView] = scrollview; + AddViewToRootContainer(AiVoiceScrollView[thisView]); + } + return true; + } + + bool AiVoiceView::ChangeAiVoicVolumeView(int16_t thisView) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoic4gServiceConView"); + if (AiVoiceScrollView[thisView] == nullptr) + { + p_AiVoiceVolumeView = new AiVoiceVolumeView(); + if (p_AiVoiceVolumeView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + UIScrollView *scrollview = p_AiVoiceVolumeView->CreateAiVoiceVolumeView(); + if (scrollview == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView); + return false; + } + AiVoiceScrollView[thisView] = scrollview; + AddViewToRootContainer(AiVoiceScrollView[thisView]); + } + return true; + } + struct AiVoiceViewMapper { const int16_t viewId; @@ -761,6 +912,9 @@ namespace OHOS {AIVOICE_NOTSETAPIKEYS, &AiVoiceView::ChangeAiVoicNotSetApiKeysView}, {AIVOICE_APIKEYS_DELETE, &AiVoiceView::ChangeAiVoicApiKeysDeleteView}, {AIVOICE_AIMODE_CONNECTING, &AiVoiceView::ChangeAiVoicConnectingView}, + {AIVOICE_SELECT_VIEW, &AiVoiceView::ChangeAiVoicSelectView}, + {AIVOICE_4GSERVICECON_VIEW, &AiVoiceView::ChangeAiVoic4gServiceConView}, + {AIVOICE_VOLUME_VIEW, &AiVoiceView::ChangeAiVoicVolumeView}, }; bool AiVoiceView::ClickFunc(int16_t interface) @@ -791,7 +945,7 @@ namespace OHOS return false; } - if (hideView < 0 || hideView >= MAX_AIVOICE_VIEWID) + if (hideView < 0 || hideView > MAX_AIVOICE_VIEWID) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CheckViewParam hideView err."); return false; @@ -802,6 +956,16 @@ namespace OHOS static const int16 AiVoiceDestroyMapper[] = { AIVOICE_AIMODE_CONNECTING, + AIVOICE_4GSERVICECON_VIEW, + AIVOICE_LISTENING_VIEWID, + AIVOICE_THINKING_VIEWID, + AIVOICE_SELECT_VIEW, + AIVOICE_CONNECT_TIMEOUT_VIEWID, + AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID, + AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID, + // AIVOICE_STARTCHAT_VIEWID, + AIVOICE_RETURN_RESULT_TEXT_VIEWID, + AIVOICE_VOLUME_VIEW, }; void AiVoiceView::DestroyTempView(int16_t hideView) @@ -828,6 +992,77 @@ namespace OHOS p_AiVoiceConnectingView = nullptr; } break; + case AIVOICE_4GSERVICECON_VIEW: + if (p_Aivoice4gServiceConView) + { + delete p_Aivoice4gServiceConView; + p_Aivoice4gServiceConView = nullptr; + } + break; + case AIVOICE_LISTENING_VIEWID: + if (p_AivoiceListeningView) + { + if (p_AivoiceListeningView) + { + delete p_AivoiceListeningView; + p_AivoiceListeningView = nullptr; + } + // p_AivoiceListeningView->StartOrStopAivoiceListeningImageAnimatorView(false); + } + break; + case AIVOICE_THINKING_VIEWID: + if (p_AivoiceThinkingView) + { + delete p_AivoiceThinkingView; + p_AivoiceThinkingView = nullptr; + // p_AivoiceThinkingView->StartOrStopAiVoiceThinkingImageAnimatorView(false); + } + break; + case AIVOICE_SELECT_VIEW: + if (p_AiVoiceSelectView) + { + delete p_AiVoiceSelectView; + p_AiVoiceSelectView = nullptr; + } + break; + case AIVOICE_CONNECT_TIMEOUT_VIEWID: + if (p_AivoiceConnectTimeoutView) + { + delete p_AivoiceConnectTimeoutView; + p_AivoiceConnectTimeoutView = nullptr; + } + break; + case AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID: + if (p_AivoiceMobileDataFailedStartView) + { + delete p_AivoiceMobileDataFailedStartView; + p_AivoiceMobileDataFailedStartView = nullptr; + } + break; + case AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID: + if (p_AiVoiceBluetoothFailedStartView) + { + delete p_AiVoiceBluetoothFailedStartView; + p_AiVoiceBluetoothFailedStartView = nullptr; + } + break; + case AIVOICE_STARTCHAT_VIEWID: + // ClearAllAiVoiceScrollView(); + break; + case AIVOICE_RETURN_RESULT_TEXT_VIEWID: + if (p_AivoiceReturnResultTextView) + { + delete p_AivoiceReturnResultTextView; + p_AivoiceReturnResultTextView = nullptr; + } + break; + case AIVOICE_VOLUME_VIEW: + if (p_AiVoiceVolumeView) + { + delete p_AiVoiceVolumeView; + p_AiVoiceVolumeView = nullptr; + } + break; default: break; } @@ -835,15 +1070,22 @@ namespace OHOS void AiVoiceView::ChangeView(int16_t hideView, int16_t showView) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeView"); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeView hideView:%d, showView:%d", hideView, showView); if (!CheckViewParam(hideView, showView)) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CheckViewParam failed."); return; } - AiVoiceScrollView[hideView]->SetVisible(false); + if (hideView != MAX_AIVOICE_VIEWID) + { + if (AiVoiceScrollView[hideView] == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceScrollView[%d] is nullptr", hideView); + return; + } + AiVoiceScrollView[hideView]->SetVisible(false); + } ClickFunc(showView); - AiVoiceScrollView[showView]->SetVisible(true); if (AiVoiceScrollView[showView] != nullptr) { AiVoiceScrollView[showView]->SetVisible(true); diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp new file mode 100644 index 000000000..81317191b --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp @@ -0,0 +1,77 @@ +#include "aivoice/include/AiVoiceVolumeView.h" +#include "aivoice/include/AiVoicePresenter.h" +#include "wearable_log.h" +#include +namespace OHOS +{ + static AiVoiceVolumeView *g_pAiVoiceVolumeView{nullptr}; + AiVoiceVolumeView::AiVoiceVolumeView() + { + g_pAiVoiceVolumeView = this; + } + + AiVoiceVolumeView::~AiVoiceVolumeView() + { + ClearAll(); + g_pAiVoiceVolumeView = nullptr; + } + + AiVoiceVolumeView *AiVoiceVolumeView::GetInstance(void) + { + return g_pAiVoiceVolumeView; + } + + void AiVoiceVolumeView::ClearAll() + { + delete p_SoundAndVibrationVolumeSettingView; + p_SoundAndVibrationVolumeSettingView = nullptr; + SystemVolumeScrollView = nullptr; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SystemVolumeView::ClearAll end!!"); + } + void AiVoiceVolumeView::SetRequestFocus() + { + if (p_SoundAndVibrationVolumeSettingView->GetVolumeProcess()) + { + p_SoundAndVibrationVolumeSettingView->GetVolumeProcess()->RequestFocus(); + } + } + + UIScrollView *AiVoiceVolumeView::CreateAiVoiceVolumeView(void) + { + if (p_SoundAndVibrationVolumeSettingView == nullptr) + { + p_SoundAndVibrationVolumeSettingView = new SoundAndVibrationVolumeSettingView(SYSTEM_VOLUME); + if (p_SoundAndVibrationVolumeSettingView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "p_SoundAndVibrationVolumeSettingView is nullptr!"); + return nullptr; + } + } + if (SystemVolumeScrollView == nullptr) + { + SystemVolumeScrollView = p_SoundAndVibrationVolumeSettingView->SetUpVolumeProcess(); + if (SystemVolumeScrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemVolumeScrollView is nullptr!"); + return nullptr; + } + } + + SetRequestFocus(); + + int SystemVolume = uapi_systemVolumeGet(); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SystemVolume = %d", SystemVolume); + p_SoundAndVibrationVolumeSettingView->GetVolumeProcess()->SetValue(SystemVolume); + + UIView::OnDragListener *dragListener = static_cast(AiVoicePresenter::GetInstance()); + if (dragListener == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::dragListener new fail!"); + return nullptr; + } + SystemVolumeScrollView->SetOnDragListener(dragListener); + + return SystemVolumeScrollView; + } + +} \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp new file mode 100644 index 000000000..f51a41253 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp @@ -0,0 +1,134 @@ +#include "aivoice/include/Aivoice4gServiceConView.h" +#include "aivoice/include/AiVoicePresenter.h" +#include "wearable_log.h" +#include "common/image_cache_manager.h" +#include "UiConfig.h" +namespace OHOS +{ + static const int16_t AI4GANILABEL_X_FIRST = 83; + static const int16_t AI4GANILABEL_Y_FIRST = 257; + static const int16_t AI4GANILABEL_WIDTH_FIRST = 300; + static const int16_t AI4GANILABEL_HEIGHT_FIRST = 48; + static const char *AI4GANILABEL_TEXT_FIRST = (char *)"服务器连接中"; + static const int16_t AI4GANILABEL_FONT_FIRST = 38; + + const char *AI4GsearchImagePath[] = { + PNG_A019_080_IMAGE_PATH, + PNG_A019_081_IMAGE_PATH, + PNG_A019_082_IMAGE_PATH, + PNG_A019_083_IMAGE_PATH, + PNG_A019_084_IMAGE_PATH, + PNG_A019_085_IMAGE_PATH, + PNG_A019_086_IMAGE_PATH, + PNG_A019_087_IMAGE_PATH, + }; + + static const int16_t AI4GALIPAY_BIND_IMAGE_X = 162; + static const int16_t AI4GALIPAY_BIND_IMAGE_Y = 112; + static const int16_t AI4GALIPAY_BIND_IMAGE_WIDTH = 128; + static const int16_t AI4GALIPAY_BIND_IMAGE_HEIGHT = 128; + static const int16_t AI4GALIPAY_BIND_IMAGE_DELAY = 100; + + static AiVoice4gServiceConView *g_pAiVoice4gServiceConView{nullptr}; + AiVoice4gServiceConView::AiVoice4gServiceConView() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoice4gServiceConView::AiVoice4gServiceConView"); + g_pAiVoice4gServiceConView = this; + } + + AiVoice4gServiceConView::~AiVoice4gServiceConView() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoice4gServiceConView::~AiVoice4gServiceConView"); + ClearAll(); + g_pAiVoice4gServiceConView = nullptr; + } + + AiVoice4gServiceConView *AiVoice4gServiceConView::GetInstance(void) + { + return g_pAiVoice4gServiceConView; + } + + void AiVoice4gServiceConView::ClearAll(void) + { + if (scrollView != nullptr) + { + scrollView->RemoveAll(); + delete label; + label = nullptr; + if (AI4GImageAni) + { + AI4GImageAni->Stop(); + delete AI4GImageAni; + AI4GImageAni = nullptr; + for (int i = 0; i < 8; i++) + { + ImageCacheManager::GetInstance().UnloadSingleRes(AI4GsearchImagePath[i]); + } + } + delete scrollView; + scrollView = nullptr; + } + } + + UIScrollView *AiVoice4gServiceConView::CreateAiVoice4gServiceConView(void) + { + if (scrollView == nullptr) + { + scrollView = new UIScrollView(); + if (scrollView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::scrollView new fail!"); + return nullptr; + } + } + scrollView->SetPosition(0, 0, 466, 466); + UIView::OnDragListener *dragListener = static_cast(AiVoicePresenter::GetInstance()); + if (dragListener == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::dragListener new fail!"); + return nullptr; + } + scrollView->SetOnDragListener(dragListener); + scrollView->SetTouchable(true); + scrollView->SetDraggable(true); + /* -------------------------------------------------------------------------- */ + label = new UILabelExt(); + if (label == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AlipayBindAni::InitExit new label fail"); + return nullptr; + } + label->SetPosition(AI4GANILABEL_X_FIRST, AI4GANILABEL_Y_FIRST, AI4GANILABEL_WIDTH_FIRST, AI4GANILABEL_HEIGHT_FIRST); + label->SetText(AI4GANILABEL_TEXT_FIRST); + label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, AI4GANILABEL_FONT_FIRST); + label->SetStyle(STYLE_TEXT_FONT, AI4GANILABEL_FONT_FIRST); + label->SetAlign(TEXT_ALIGNMENT_CENTER); + label->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION); + scrollView->Add(label); + /* -------------------------------------------------------------------------- */ + AI4GImageAni = new UIImageAnimatorView(); + if (AI4GImageAni == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AlipayBindAni::AlipayInitImageAni new AI4GImageAni fail"); + return nullptr; + } + for (uint8_t i = 0; i < 8; i++) + { + AI4GsearchImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(AI4GsearchImagePath[i]); + AI4GsearchImageInfo[i].imageType = IMG_SRC_IMAGE_INFO; + AI4GsearchImageInfo[i].pos.x = AI4GALIPAY_BIND_IMAGE_X; + AI4GsearchImageInfo[i].pos.y = AI4GALIPAY_BIND_IMAGE_Y; + AI4GsearchImageInfo[i].width = AI4GALIPAY_BIND_IMAGE_WIDTH; + AI4GsearchImageInfo[i].height = AI4GALIPAY_BIND_IMAGE_HEIGHT; + } + AI4GImageAni->SetPosition(AI4GALIPAY_BIND_IMAGE_X, AI4GALIPAY_BIND_IMAGE_Y, AI4GALIPAY_BIND_IMAGE_WIDTH, AI4GALIPAY_BIND_IMAGE_HEIGHT); + AI4GImageAni->SetImageAnimatorSrc(AI4GsearchImageInfo, 8, AI4GALIPAY_BIND_IMAGE_DELAY); + AI4GImageAni->SetRepeat(true); + AI4GImageAni->SetAutoEnable(false); + AI4GImageAni->SetResizeMode(UIImageView::FILL); + scrollView->Add(AI4GImageAni); + AI4GImageAni->Start(); + + return scrollView; + } +} diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceChatContentListItemView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceChatContentListItemView.cpp index a5b9590c7..48c92bd58 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceChatContentListItemView.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceChatContentListItemView.cpp @@ -23,6 +23,11 @@ namespace OHOS static constexpr const int16_t CHATCONTENTLABEL_TEXT_FONT = 26; static constexpr const int16_t CHATCONTENTLABEL_LINE_HEIGHT = 30; + static constexpr const int16_t MINDLABEL_X = 40; + static constexpr const int16_t MINDLABEL_Y = 25; + static constexpr const int16_t MINDLABEL_TEXT_FONT = 20; + static constexpr const int16_t MINDLABEL_LINE_HEIGHT = 26; + static constexpr const int64_t RADIUS = 20; static constexpr const int16_t QUESTION_CHATCONTENTIMAGE_X = 0; @@ -54,6 +59,7 @@ namespace OHOS SetUpChild(); Add(&chatContentImage); chatContentScrollView.Add(&chatContentLabel); + chatContentScrollView.Add(&mindLabel); Add(&chatContentScrollView); } @@ -61,6 +67,7 @@ namespace OHOS { Remove(&chatContentImage); chatContentScrollView.Remove(&chatContentLabel); + chatContentScrollView.Remove(&mindLabel); Remove(&chatContentScrollView); } @@ -88,12 +95,24 @@ namespace OHOS } else { - if(!AiVoiceModel::GetInstance().GetIsLimitDisplayed()) + if (!AiVoiceModel::GetInstance().GetIsLimitDisplayed()) { AiVoiceModel::GetInstance().SetIsLimitDisplayed(true); - chatContentLabel.SetLineBreakMode(isAiAnswerFlag ? UILabel::LINE_BREAK_ELLIPSIS : UILabel::LINE_BREAK_WRAP);//超过高度在末尾用省略号替换 + chatContentLabel.SetLineBreakMode(isAiAnswerFlag ? UILabel::LINE_BREAK_ELLIPSIS : UILabel::LINE_BREAK_WRAP); // 超过高度在末尾用省略号替换 } } + + if(isAiAnswerFlag) + { + chatContentScrollView.Resize(isAiAnswerFlag ? QUESTION_CHATCONTENTSCROLLVIEW_W : ANSWER_CHATCONTENTSCROLLVIEW_W, GetHeight()); + mindLabel.SetY(chatContentScrollView.GetY() + chatContentScrollView.GetHeight()- 40); + mindLabel.SetVisible(true); + } + else + { + chatContentScrollView.Resize(isAiAnswerFlag ? QUESTION_CHATCONTENTSCROLLVIEW_W : ANSWER_CHATCONTENTSCROLLVIEW_W, GetHeight() - 30); + mindLabel.SetVisible(false); + } } void AivoiceChatContentListItemView::SetUpChild() @@ -115,6 +134,17 @@ namespace OHOS chatContentLabel.SetLineBreakMode(UILabel::LINE_BREAK_WRAP); chatContentLabel.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); chatContentLabel.SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, CHATCONTENTLABEL_TEXT_FONT); + + mindLabel.SetPosition(MINDLABEL_X, MINDLABEL_Y); + mindLabel.Resize(0, 26); + mindLabel.SetVisible(false); + mindLabel.SetText("内容由AI生成,仅供参考"); + mindLabel.SetStyle(STYLE_TEXT_FONT, MINDLABEL_TEXT_FONT); + mindLabel.SetStyle(STYLE_LINE_HEIGHT, MINDLABEL_LINE_HEIGHT); + mindLabel.SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); + mindLabel.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); + mindLabel.SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, MINDLABEL_TEXT_FONT); + mindLabel.SetTextColor(Color::GetColorFromRGBA(0x99, 0x99, 0x99, 0xff)); } } \ No newline at end of file diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceListeningView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceListeningView.cpp index 050d4522d..41e1b2b0a 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceListeningView.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceListeningView.cpp @@ -14,6 +14,48 @@ // #include "common/image_cache_manager.h" namespace OHOS { + const char *listening_path_array[] = { + "/user/res/AIVoice/AIVoiceListening/1.bin", + "/user/res/AIVoice/AIVoiceListening/2.bin", + "/user/res/AIVoice/AIVoiceListening/3.bin", + "/user/res/AIVoice/AIVoiceListening/4.bin", + "/user/res/AIVoice/AIVoiceListening/5.bin", + "/user/res/AIVoice/AIVoiceListening/6.bin", + "/user/res/AIVoice/AIVoiceListening/7.bin", + "/user/res/AIVoice/AIVoiceListening/8.bin", + "/user/res/AIVoice/AIVoiceListening/9.bin", + "/user/res/AIVoice/AIVoiceListening/10.bin", + "/user/res/AIVoice/AIVoiceListening/11.bin", + "/user/res/AIVoice/AIVoiceListening/12.bin", + "/user/res/AIVoice/AIVoiceListening/13.bin", + "/user/res/AIVoice/AIVoiceListening/14.bin", + "/user/res/AIVoice/AIVoiceListening/15.bin", + "/user/res/AIVoice/AIVoiceListening/16.bin", + "/user/res/AIVoice/AIVoiceListening/17.bin", + "/user/res/AIVoice/AIVoiceListening/18.bin", + "/user/res/AIVoice/AIVoiceListening/19.bin", + "/user/res/AIVoice/AIVoiceListening/20.bin", + "/user/res/AIVoice/AIVoiceListening/21.bin", + "/user/res/AIVoice/AIVoiceListening/22.bin", + "/user/res/AIVoice/AIVoiceListening/23.bin", + "/user/res/AIVoice/AIVoiceListening/24.bin", + "/user/res/AIVoice/AIVoiceListening/25.bin", + "/user/res/AIVoice/AIVoiceListening/26.bin", + "/user/res/AIVoice/AIVoiceListening/27.bin", + "/user/res/AIVoice/AIVoiceListening/28.bin", + "/user/res/AIVoice/AIVoiceListening/29.bin", + "/user/res/AIVoice/AIVoiceListening/30.bin", + "/user/res/AIVoice/AIVoiceListening/31.bin", + "/user/res/AIVoice/AIVoiceListening/32.bin", + "/user/res/AIVoice/AIVoiceListening/33.bin", + "/user/res/AIVoice/AIVoiceListening/34.bin", + "/user/res/AIVoice/AIVoiceListening/35.bin", + "/user/res/AIVoice/AIVoiceListening/36.bin", + "/user/res/AIVoice/AIVoiceListening/37.bin", + "/user/res/AIVoice/AIVoiceListening/38.bin", + "/user/res/AIVoice/AIVoiceListening/39.bin", + "/user/res/AIVoice/AIVoiceListening/40.bin", + }; static AivoiceListeningView *g_pAivoiceListeningView{nullptr}; @@ -53,8 +95,10 @@ namespace OHOS AiVoiceListeningImageAnimatorView->Stop(); delete AiVoiceListeningImageAnimatorView; AiVoiceListeningImageAnimatorView = nullptr; - - FreeImageInfoArray(AiVoiceListeningPathsArray, AIVoiceListeningImagePaths, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); + for (int i = 0; i < AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++) + { + ImageCacheManager::GetInstance().UnloadSingleRes(listening_path_array[i]); + } } if (showtimeout != nullptr) @@ -109,7 +153,7 @@ namespace OHOS button->SetViewId(buttonconfig.ViewId); button->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); button->SetStyle(STYLE_BACKGROUND_OPA, 0xff); - button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED); + button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff191919, UIButton::PRESSED); return button; } @@ -141,7 +185,7 @@ namespace OHOS animatorView->SetSizeFixed(true); // animatorView->SetAutoEnable(false); // animatorView->SetResizeMode(UIImageAnimatorView::FILL); - animatorView->Start(); + // animatorView->Start(); return animatorView; } @@ -252,33 +296,45 @@ namespace OHOS bool AivoiceListeningView::CreateAivoiceListeningImageAnimator(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AivoiceListeningView::CreateAivoiceListeningImageAnimator"); - AiVoiceListeningPathsArray = CreateImageInfoArray(AIVoiceListeningImagePaths, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); - if (AiVoiceListeningPathsArray == nullptr) + if (AiVoiceListeningImageAnimatorView == nullptr) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceListeningView::AiVoiceListeningPathsArray is nullptr!!"); - return false; + AiVoiceListeningImageAnimatorView = new UIImageAnimatorView(); + if (AiVoiceListeningImageAnimatorView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AlipayBindAni::AlipayInitImageAni new AI4GImageAni fail"); + return false; + } } - - ImageAnimatorConfig imageanimatorconfig = { - .x = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_X, - .y = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_Y, - .width = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_W, - .height = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_H, - .imageInfoArray = AiVoiceListeningImageInfo, - .pathsArray = AiVoiceListeningPathsArray, - .numFrames = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, - .delay = AIVOICE_LISTENING_IMAGE_ANIMATOR_DELAY, - }; - AiVoiceListeningImageAnimatorView = AivoiceListeningImageAnimatorInit(imageanimatorconfig); - if (AiVoiceListeningImageAnimatorView == nullptr) + for (uint8_t i = 0; i < AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceListeningImageAnimatorView::AiVoiceListeningImageAnimatorView new fail"); - return false; + AiVoiceListeningImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(listening_path_array[i]); + AiVoiceListeningImageInfo[i].imageType = IMG_SRC_IMAGE_INFO; + AiVoiceListeningImageInfo[i].pos.x = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_X; + AiVoiceListeningImageInfo[i].pos.y = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_Y; + AiVoiceListeningImageInfo[i].width = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_W; + AiVoiceListeningImageInfo[i].height = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_H; } + AiVoiceListeningImageAnimatorView->SetPosition(AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_X, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_Y, + AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_W, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_H); + AiVoiceListeningImageAnimatorView->SetImageAnimatorSrc(AiVoiceListeningImageInfo, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, AIVOICE_LISTENING_IMAGE_ANIMATOR_DELAY); + AiVoiceListeningImageAnimatorView->SetRepeat(true); + AiVoiceListeningImageAnimatorView->SetAutoEnable(false); + AiVoiceListeningImageAnimatorView->SetResizeMode(UIImageView::FILL); return true; } + void AivoiceListeningView::StartOrStopAivoiceListeningImageAnimatorView(bool val) + { + if (AiVoiceListeningImageAnimatorView) + { + if (val) + AiVoiceListeningImageAnimatorView->Start(); + else + AiVoiceListeningImageAnimatorView->Stop(); + } + } + UIScrollView *AivoiceListeningView::CreateAivoiceListeningView(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AivoiceListeningView::CreateAivoiceListeningView"); diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceReturnResultTextView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceReturnResultTextView.cpp index e81a42d23..be4722755 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceReturnResultTextView.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceReturnResultTextView.cpp @@ -115,6 +115,13 @@ namespace OHOS scrollView = nullptr; } } + void AivoiceReturnResultTextView::SetRequestFocus() + { + if (chatContentList) + { + chatContentList->RequestFocus(); + } + } UILabelExt *AivoiceReturnResultTextView::AivoiceReturnResultTextLabelInit(LabelConfig &labelconfig) { @@ -252,8 +259,8 @@ namespace OHOS chatContentList->SetMaxScrollDistance(MAX_SCR_DIS); chatContentList->SetSwipeACCLevel(200); // 800: compensation distance chatContentList->SetDragACCLevel(5); // 5: drag acceleration - chatContentList->SetRotateFactor(2); - chatContentList->RequestFocus(); + // chatContentList->SetRotateFactor(2); + // chatContentList->RequestFocus(); // chatContentList->SetIntercept(true); chatContentList->SetAdapter(chatContentListAdapter); chatContentList->RefreshList(); diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceThinkingView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceThinkingView.cpp index 6e7db531a..30984de7f 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceThinkingView.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceThinkingView.cpp @@ -15,6 +15,49 @@ namespace OHOS { + const char *thinking_path_array[] = { + "/user/res/AIVoice/AIVoiceThinking/1.bin", + "/user/res/AIVoice/AIVoiceThinking/2.bin", + "/user/res/AIVoice/AIVoiceThinking/3.bin", + "/user/res/AIVoice/AIVoiceThinking/4.bin", + "/user/res/AIVoice/AIVoiceThinking/5.bin", + "/user/res/AIVoice/AIVoiceThinking/6.bin", + "/user/res/AIVoice/AIVoiceThinking/7.bin", + "/user/res/AIVoice/AIVoiceThinking/8.bin", + "/user/res/AIVoice/AIVoiceThinking/9.bin", + "/user/res/AIVoice/AIVoiceThinking/10.bin", + "/user/res/AIVoice/AIVoiceThinking/11.bin", + "/user/res/AIVoice/AIVoiceThinking/12.bin", + "/user/res/AIVoice/AIVoiceThinking/13.bin", + "/user/res/AIVoice/AIVoiceThinking/14.bin", + "/user/res/AIVoice/AIVoiceThinking/15.bin", + "/user/res/AIVoice/AIVoiceThinking/16.bin", + "/user/res/AIVoice/AIVoiceThinking/17.bin", + "/user/res/AIVoice/AIVoiceThinking/18.bin", + "/user/res/AIVoice/AIVoiceThinking/19.bin", + "/user/res/AIVoice/AIVoiceThinking/20.bin", + "/user/res/AIVoice/AIVoiceThinking/21.bin", + "/user/res/AIVoice/AIVoiceThinking/22.bin", + "/user/res/AIVoice/AIVoiceThinking/23.bin", + "/user/res/AIVoice/AIVoiceThinking/24.bin", + "/user/res/AIVoice/AIVoiceThinking/25.bin", + "/user/res/AIVoice/AIVoiceThinking/26.bin", + "/user/res/AIVoice/AIVoiceThinking/27.bin", + "/user/res/AIVoice/AIVoiceThinking/28.bin", + "/user/res/AIVoice/AIVoiceThinking/29.bin", + "/user/res/AIVoice/AIVoiceThinking/30.bin", + "/user/res/AIVoice/AIVoiceThinking/31.bin", + "/user/res/AIVoice/AIVoiceThinking/32.bin", + "/user/res/AIVoice/AIVoiceThinking/33.bin", + "/user/res/AIVoice/AIVoiceThinking/34.bin", + "/user/res/AIVoice/AIVoiceThinking/35.bin", + "/user/res/AIVoice/AIVoiceThinking/36.bin", + "/user/res/AIVoice/AIVoiceThinking/37.bin", + "/user/res/AIVoice/AIVoiceThinking/38.bin", + "/user/res/AIVoice/AIVoiceThinking/39.bin", + "/user/res/AIVoice/AIVoiceThinking/40.bin", + }; + static AivoiceThinkingView *g_pAivoiceThinkingView{nullptr}; AivoiceThinkingView::AivoiceThinkingView() @@ -54,8 +97,11 @@ namespace OHOS delete AiVoiceThinkingImageAnimatorView; AiVoiceThinkingImageAnimatorView = nullptr; - // FreeImagePathsArray(AiVoiceThinkingPathsArray, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); - FreeImageInfoArray(AiVoiceThinkingPathsArray, AIVoiceThinkingImagePaths, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); + for (int i = 0; i < AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++) + { + ImageCacheManager::GetInstance().UnloadSingleRes(thinking_path_array[i]); + } + } if (cancelThink != nullptr) @@ -104,7 +150,7 @@ namespace OHOS button->SetViewId(buttonconfig.ViewId); button->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919); button->SetStyle(STYLE_BACKGROUND_OPA, 0xff); - button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED); + button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff191919, UIButton::PRESSED); return button; } @@ -136,7 +182,7 @@ namespace OHOS animatorView->SetSizeFixed(true); // animatorView->SetAutoEnable(false); // animatorView->SetResizeMode(UIImageAnimatorView::FILL); - animatorView->Start(); + // animatorView->Start(); return animatorView; } @@ -235,52 +281,48 @@ namespace OHOS bool AivoiceThinkingView::CreateAivoiceThinkingImageAnimator(void) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingImageAnimator"); - AiVoiceThinkingPathsArray = CreateImageInfoArray(AIVoiceThinkingImagePaths, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES); - if (AiVoiceThinkingPathsArray == nullptr) + if (AiVoiceThinkingImageAnimatorView == nullptr) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::AiVoiceThinkingPathsArray is nullptr!!"); - return false; + AiVoiceThinkingImageAnimatorView = new UIImageAnimatorView(); + if (AiVoiceThinkingImageAnimatorView == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::AivoiceThinkingImageAnimatorView new fail"); + return false; + } } - - ImageAnimatorConfig imageanimatorconfig = { - .x = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_X, - .y = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_Y, - .width = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_W, - .height = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_H, - .imageInfoArray = AiVoiceThinkingImageInfo, - .pathsArray = AiVoiceThinkingPathsArray, - .numFrames = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, - .delay = AIVOICE_THINKING_IMAGE_ANIMATOR_DELAY, - }; - AiVoiceThinkingImageAnimatorView = AivoiceThinkingImageAnimatorInit(imageanimatorconfig); - if (AiVoiceThinkingImageAnimatorView == nullptr) + for (uint8_t i = 0; i < AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceThinkingImageAnimatorView::AiVoiceThinkingImageAnimatorView new fail"); - return false; + AiVoiceThinkingImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(thinking_path_array[i]); + AiVoiceThinkingImageInfo[i].imageType = IMG_SRC_IMAGE_INFO; + AiVoiceThinkingImageInfo[i].pos.x = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_X; + AiVoiceThinkingImageInfo[i].pos.y = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_Y; + AiVoiceThinkingImageInfo[i].width = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_W; + AiVoiceThinkingImageInfo[i].height = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_H; } + AiVoiceThinkingImageAnimatorView->SetPosition(AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_X, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_Y, + AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_W, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_H); + AiVoiceThinkingImageAnimatorView->SetImageAnimatorSrc(AiVoiceThinkingImageInfo, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, AIVOICE_THINKING_IMAGE_ANIMATOR_DELAY); + AiVoiceThinkingImageAnimatorView->SetRepeat(true); + AiVoiceThinkingImageAnimatorView->SetAutoEnable(false); + AiVoiceThinkingImageAnimatorView->SetResizeMode(UIImageView::FILL); return true; } - UIScrollView *AivoiceThinkingView::CreateAivoiceThinkingView(void) + void AivoiceThinkingView::StartOrStopAiVoiceThinkingImageAnimatorView(bool val) { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingView"); -#if 0 - if (scrollView == nullptr) + if (AiVoiceThinkingImageAnimatorView != nullptr) { - if (!CreateAivoiceThinkingScrollView() || !CreateAivoiceThinkingLabel() || - !CreateAivoiceThinkingButton() || !CreateAivoiceThinkingImageAnimator()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingView fail!!"); - return nullptr; - } - - scrollView->Add(title); - scrollView->Add(AiVoiceThinkingImageAnimatorView); - scrollView->Add(cancelThinkButton); - scrollView->Add(cancelThink); + if (val) + AiVoiceThinkingImageAnimatorView->Start(); + else + AiVoiceThinkingImageAnimatorView->Stop(); } -#endif + } + + UIScrollView *AivoiceThinkingView::CreateAivoiceThinkingView(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingView"); if (!CreateAivoiceThinkingScrollView()) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingScrollView fail!!"); diff --git a/code/sdk/zhihui/ai/include/cat1_ws.h b/code/sdk/zhihui/ai/include/cat1_ws.h index 877e5a3de..b45ef6927 100644 --- a/code/sdk/zhihui/ai/include/cat1_ws.h +++ b/code/sdk/zhihui/ai/include/cat1_ws.h @@ -1,5 +1,8 @@ #ifndef __CAT1_WS_H__ #define __CAT1_WS_H__ + +#include "bk_websocket.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -22,6 +25,8 @@ void uapi_UI_stop_start_asr_timeout(void); bool uapi_get_server_state_is_end(void); +void ai_cleanup_resources(void); + typedef enum { AI_TYPE_0=0, -- 2.17.1