From a405e30fe4111c633c0995d7630adb5c34881322 Mon Sep 17 00:00:00 2001 From: xue <2144439972@qq.com> Date: Mon, 12 Jan 2026 22:55:10 +0800 Subject: [PATCH] =?utf8?q?=E5=A2=9E=E5=8A=A0=E5=8E=8B=E6=B5=8BAT=E6=8C=87?= =?utf8?q?=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../nativeui/include/uiservice/ui_service.h | 1 + .../thunderbird/include/ThunderBirdModel.h | 2 + .../thunderbird/src/ThunderBirdModel.cpp | 43 ++++++++++- .../nativeui/uiservice/src/ui_service.cpp | 10 +++ .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 29 ++++++- .../leiniao/ln_api_cpp/ln_api_interface.cpp | 7 ++ .../leiniao/ln_api_cpp/ln_api_interface.h | 2 + .../leiniao/ln_api_cpp/ln_audio_simple.cpp | 76 +++++++++++++++++++ .../leiniao/ln_api_cpp/ln_audio_simple.h | 11 +++ 9 files changed, 176 insertions(+), 5 deletions(-) diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/include/uiservice/ui_service.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/include/uiservice/ui_service.h index 85bba0198..44d6aa9c8 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/include/uiservice/ui_service.h +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/include/uiservice/ui_service.h @@ -78,6 +78,7 @@ typedef enum { HAND_VAD_INITIALIZED_NOTIFY, // VAD初始化完成通知 HAND_BLUETOOTH_CONNECT_NOTIFY, // 蓝牙耳机连接通知 HAND_BLUETOOTH_EARPHONE_CONNECT_STATUS_NOTIFY, // 蓝牙耳机连接状态通知 + HAND_JUMP_DIALOGUE_SPEAKING_NOTIFY, // 跳转到对话说话界面通知 MAX_NUM_HANDLER, } UiServiceMsgId; diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h index f07431641..4b6c8c958 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h @@ -246,6 +246,8 @@ namespace OHOS // 处理对话响应消息的finished标志 void HandleDialogueResponseFinished(bool finished); + // 处理跳转到对话说话界面 + void HandleJumpDialogueSpeaking(); // 减低视频帧率 void LowFrequence(); // 恢复视频帧率 diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp index 033cb9091..8dac21cf6 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp @@ -27,7 +27,6 @@ #include #include #include "custom_utils.h" -#include #include "bluetooth/Ln_Bluetooth_apiC.h" #include #include @@ -54,6 +53,7 @@ #include "ConfigModelC.h" #include "ConfigModel.h" #include "cmsis_os2.h" +#include "los_task.h" #include "custom_runtime.h" #include "ln_api_interface.h" #ifdef __cplusplus @@ -61,6 +61,8 @@ extern "C" { #endif #include "imsl_vad.h" #include "dmp_api.h" +#include +#include #ifdef __cplusplus } #endif @@ -2968,7 +2970,44 @@ extern "C" { m_dialogueModeFinished = true; } } - + + void ThunderBirdModel::HandleJumpDialogueSpeaking() + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking"); + + // 1. 停止其他音频服务,避免冲突 + ln_audio_simple_stop(); + AI_ForceInterrupt(); + do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_AUDIO_DEINIT, NULL, 0); + + // 2. 设置常亮屏 + ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); + + // 3. 跳转到对话说话界面 + if (ThunderBirdMainView::GetInstance()) { + int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); + ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING); + } + + int32_t uiVolume = get_ui_volume(); + if (uiVolume <= 0 || uiVolume > 100) { + uiVolume = 50; // 默认音量50% + } + AudioServiceSetVolume(AUDIO_STREAM_ALARM_CLOCK, uiVolume); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Set ALARM_CLOCK volume to %d%%", uiVolume); + + // 5. 循环播放 FactoryMode.mp3(使用 ln_audio_simple_play_loop,支持循环播放,无需线程) + const char *factory_mode_file = "/user/res/music/FactoryMode.mp3"; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Playing file: %s (will loop)", factory_mode_file); + + // 使用 ln_audio_simple_play_loop 直接循环播放,无需线程 + int ret = ln_audio_simple_play_loop(factory_mode_file, true); + if (ret != 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Failed to play file: %s, ret=%d", factory_mode_file, ret); + } else { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleJumpDialogueSpeaking: Successfully started loop playback"); + } + } void ThunderBirdModel::HandleBluetoothConnect(const char *bluetoothAddress) { auto* mainView = ThunderBirdMainView::GetInstance(); diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/uiservice/src/ui_service.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/uiservice/src/ui_service.cpp index 99210d450..f1d626d8b 100644 --- a/code/sdk/application/wearable/ln/nativeapp/nativeui/uiservice/src/ui_service.cpp +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/uiservice/src/ui_service.cpp @@ -119,6 +119,7 @@ static void HandDialogueResponseFinishedNotify(Request *request); static void HandVadInitializedNotify(Request *request); static void HandBluetoothConnectNotify(Request *request); static void HandBluetoothEarphoneConnectStatusNotify(Request *request); +static void HandJumpDialogueSpeakingNotify(Request *request); // 消息处理程序项数组(每个消息类型对应一个处理函数,函数名以 Handle 开头) MsgHandlerEntry msgHandlers[] = { @@ -150,6 +151,7 @@ MsgHandlerEntry msgHandlers[] = { {HAND_VAD_INITIALIZED_NOTIFY,HandVadInitializedNotify}, {HAND_BLUETOOTH_CONNECT_NOTIFY,HandBluetoothConnectNotify}, {HAND_BLUETOOTH_EARPHONE_CONNECT_STATUS_NOTIFY,HandBluetoothEarphoneConnectStatusNotify}, + {HAND_JUMP_DIALOGUE_SPEAKING_NOTIFY,HandJumpDialogueSpeakingNotify}, }; /* -------------------------------------------------------------------------- */ void ScreenTurnOn(int32_t timeout) @@ -923,6 +925,14 @@ void HandBluetoothEarphoneConnectStatusNotify(Request *request) OHOS::ThunderBirdModel::GetInstance(), connectStatus)); } } + +// 跳转到对话说话界面通知 +void HandJumpDialogueSpeakingNotify(Request *request) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandJumpDialogueSpeakingNotify msg_id = %d", request->msgId); + GraphicService::GetInstance()->PostGraphicEvent( + std::bind(&OHOS::ThunderBirdModel::HandleJumpDialogueSpeaking,OHOS::ThunderBirdModel::GetInstance())); +} /* -------------------------------------------------------------------------- */ #ifdef __cplusplus } diff --git a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c index 09ecff6c9..a5dbce812 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -11,6 +11,7 @@ #include "errcode.h" #include "ln_api.h" #include "ln_api_interface.h" +#include "ln_audio_simple.h" #include "cJSON.h" #include "broadcast_feature.h" #include "bts_br_gap.h" @@ -1931,6 +1932,26 @@ static uint32_t ln_ws_set_log_level_at(uint8_t *para, uint32_t paraLen, char *st return ERRCODE_SUCC; } +/* AT^LN_STRESS_TEST_DIALOGUE - 压测模式:跳转到对话说话界面,常亮屏且循环播放FactoryMode.mp3 */ +static uint32_t ln_stress_test_dialogue_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + LN_UNUSED(para); + LN_UNUSED(paraLen); + LN_UNUSED(strCommonCmd); + + printf("[LN][STRESS_TEST_DIALOGUE] Starting stress test mode: jump to dialogue speaking view, screen always on and loop play FactoryMode.mp3\n"); + + // 发送跳转到对话说话界面的通知 + push_jump_dialogue_speaking_notification(); + + printf("[LN][STRESS_TEST_DIALOGUE] Stress test mode enabled:\n"); + printf(" - Jump to THUNDERBIRD_DIALOGUEVIEW_SPEAKING\n"); + printf(" - Screen always on enabled\n"); + printf(" - Loop playback: /user/res/music/FactoryMode.mp3\n"); + + return ERRCODE_SUCC; +} + static const at_cmd_table_t g_ln_api_cmd[] = { /* ---------------------------------- 雷鸟API --------------------------------- */ {(char *)"AT^LN_GET_TOKEN", ln_get_device_token_at, (char *)"获取雷鸟设备Token: AT^LN_GET_TOKEN[=deviceId,deviceIccid,deviceModel,deviceVersion]"}, @@ -2014,8 +2035,8 @@ static const at_cmd_table_t g_ln_api_cmd[] = { {(char *)"AT^LN_DEBUG_POPUP", ln_debug_popup_at, (char *)"debug界面弹窗提示: AT^LN_DEBUG_POPUP[=message]"}, //帧率控制 - {(char *)"AT^LN_SET_FPS", ln_set_fps_at, (char *)"设置帧率: AT^LN_SET_FPS="}, - {(char *)"AT^LN_GET_FPS", ln_get_fps_at, (char *)"获取当前帧率: AT^LN_GET_FPS"}, + // {(char *)"AT^LN_SET_FPS", ln_set_fps_at, (char *)"设置帧率: AT^LN_SET_FPS="}, + // {(char *)"AT^LN_GET_FPS", ln_get_fps_at, (char *)"获取当前帧率: AT^LN_GET_FPS"}, //WS状态和网络参数显示 {(char *)"AT^LN_SHOW_WS_NET", ln_show_ws_net_at, (char *)"显示WS连接状态和网络参数: AT^LN_SHOW_WS_NET[=-p x,y]"}, @@ -2031,7 +2052,9 @@ static const at_cmd_table_t g_ln_api_cmd[] = { {(char *)"AT^LN_BT_DISCONNECT", ln_bt_disconnect_at, (char *)"断开蓝牙设备: AT^LN_BT_DISCONNECT=AA:BB:CC:DD:EE:FF"}, //WebSocket日志等级设置 - {(char *)"AT^LN_WS_LOG_LEVEL", ln_ws_set_log_level_at, (char *)"设置WebSocket日志等级: AT^LN_WS_LOG_LEVEL=0-3"}, + {(char *)"AT^LN_WS_LOG_LEVEL", ln_ws_set_log_level_at, (char *)"设置WebSocket日志等级: AT^LN_WS_LOG_LEVEL=0-3"}, + //压测相关 + {(char *)"AT^LN_STRESS_TEST_DIALOGUE", ln_stress_test_dialogue_at, (char *)"压测模式:跳转到对话说话界面,常亮屏且循环播放FactoryMode.mp3: AT^LN_STRESS_TEST_DIALOGUE"}, }; diff --git a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.cpp b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.cpp index 1e9845c93..2593e4450 100644 --- a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.cpp +++ b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.cpp @@ -325,6 +325,13 @@ void push_dialogue_response_finished_notification(bool finished) SendMsgToUIService(HAND_DIALOGUE_RESPONSE_FINISHED_NOTIFY, 0, &finished, sizeof(finished)); } +//通知跳转到对话说话界面 +void push_jump_dialogue_speaking_notification(void) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JUMP_DIALOGUE_SPEAKING] Jump to dialogue speaking view"); + SendMsgToUIService(HAND_JUMP_DIALOGUE_SPEAKING_NOTIFY, 0, NULL, 0); +} + //通知VAD初始化完成 void push_vad_initialized_notification(void) { diff --git a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h index 2d5825412..88f6d1957 100644 --- a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h +++ b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h @@ -119,6 +119,8 @@ void push_upgrade_description_notification(const char *description); void push_story_response_finished_notification(bool finished); //通知对话响应finished void push_dialogue_response_finished_notification(bool finished); +//通知跳转到对话说话界面 +void push_jump_dialogue_speaking_notification(void); //通知VAD初始化完成 void push_vad_initialized_notification(void); //通知进行蓝牙耳机连接操作 diff --git a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp index 49da1ba5a..124bbb2e1 100644 --- a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp +++ b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp @@ -284,6 +284,82 @@ int ln_audio_simple_play(const char *file_path) return 0; } +int ln_audio_simple_play_loop(const char *file_path, bool loop) +{ + if (!file_path || file_path[0] == '\0') + { + printf("[LN_AUDIO_SIMPLE] invalid file path\n"); + return -1; + } + + if (!AudioInitOnce()) + return -2; + + // 设置播放器回调 + g_simple.player->SetPlayerCallback(g_player_callback); + + // 设置音频源 + g_simple.source = std::make_shared(file_path, g_simple.header); + if (!g_simple.source) + { + printf("[LN_AUDIO_SIMPLE] create Source failed\n"); + return -3; + } + + int32_t ret; + ret = g_simple.player->SetSource(*g_simple.source); + if (ret != 0) + { + printf("[LN_AUDIO_SIMPLE] SetSource failed: %d\n", ret); + g_simple.player->Reset(); + return -4; + } + + // 设置循环播放 + g_simple.player->EnableSingleLooping(loop); + g_simple.player->SetAudioStreamType(AUDIO_STREAM_ALARM_CLOCK); + + // 在 Prepare 之前激活音频中断,因为 Prepare 时会创建音频流,需要有效的音频中断会话 + if (!EnsureAudioInterrupt()) + { + g_simple.player->Reset(); + return -6; + } + + ret = g_simple.player->Prepare(); + if (ret != 0) + { + printf("[LN_AUDIO_SIMPLE] Prepare failed: %d\n", ret); + g_simple.player->Reset(); + ClearAudioInterrupt(); + return -5; + } + + ret = g_simple.player->SetAudioSessionId(g_simple.sessionId); + if (ret != 0) + { + printf("[LN_AUDIO_SIMPLE] SetAudioSessionId failed: %d\n", ret); + g_simple.player->Reset(); + ClearAudioInterrupt(); + return -7; + } + + ret = g_simple.player->Play(); + if (ret != 0) + { + printf("[LN_AUDIO_SIMPLE] Play failed: %d\n", ret); + g_simple.player->Stop(); + g_simple.player->Reset(); + ClearAudioInterrupt(); + return -8; + } + + g_simple.is_playing = true; + g_simple.is_paused = false; + printf("[LN_AUDIO_SIMPLE] started: %s (loop=%s)\n", file_path, loop ? "true" : "false"); + return 0; +} + int ln_audio_simple_stop(void) { if (!g_simple.player) diff --git a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h index 70eaf9c57..61f578304 100644 --- a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h +++ b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h @@ -29,6 +29,17 @@ extern "C" { */ int ln_audio_simple_play(const char *file_path); +/* + * 播放本地音频文件(支持循环播放) + * 参数: + * file_path - 音频文件的绝对路径 + * loop - 是否循环播放 + * 返回: + * 0 成功启动播放(异步) + * <0 失败 + */ +int ln_audio_simple_play_loop(const char *file_path, bool loop); + /* * 主动停止播放(同步停止,确保资源释放) * 返回:0 成功,<0 失败 -- 2.17.1