430 lines
14 KiB
C++
430 lines
14 KiB
C++
/*
|
||
* Copyright (c) CompanyNameMagicTag 2021-2021. All rights reserved.
|
||
* Description: broadcast feature implement
|
||
* Author: CompanyName
|
||
* Create: 2021-11-11
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include "msg_center.h"
|
||
#include "xiaodu_voice.h"
|
||
#include "msg_center_protocol.h"
|
||
#include "msg_center_cmd.h"
|
||
#include "wearable_log.h"
|
||
#if defined(SUPPORT_POWER_MANAGER)
|
||
#include "power_display_service.h"
|
||
#endif
|
||
#include "common_def.h"
|
||
#include "player_sample_wrapper.h"
|
||
#include "soc_osal.h"
|
||
#include "watchdog.h"
|
||
#include "js_ability.h"
|
||
#include "recording_module.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define TTS_AUDIO_PARA_LEN 100
|
||
#define TTS_MEDIA_MAX_PARAM_CNT 10
|
||
#define TTS_MEDIA_PARAM_OFFSET 2
|
||
#define TASK_PRIORITY_PCM_STREAM (osPriority_t)(40)
|
||
#define PCM_STREAM_MSG_STACK_SIZE 0xC00
|
||
|
||
osMessageQueueId_t g_pcm_stream_msg_queue_id = nullptr;
|
||
static bool g_pcm_stream_end_record_sended_flag = false; /* 标识pcm的end帧是否发送完成,用于异常场景时资源清理 */
|
||
|
||
|
||
static errcode_t pcm_stream_task_init(void)
|
||
{
|
||
osMessageQueueAttr_t m_attr = {0};
|
||
m_attr.name = "PCM_STREAM_MSG";
|
||
g_pcm_stream_msg_queue_id = osMessageQueueNew(PCM_STREAM_MSG_QUEUE_LEN, sizeof(pcm_stream_queue_msg), &m_attr);
|
||
if (g_pcm_stream_msg_queue_id == nullptr) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "create msg queue fail\r\n");
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "create msg queue succ\r\n");
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
static void pcm_stream_del_queue(void)
|
||
{
|
||
osStatus_t ret;
|
||
|
||
ret = osMessageQueueDelete(g_pcm_stream_msg_queue_id);
|
||
if (ret != osOK) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "del pcm_stream queue fail, ret = %u\r\n", ret);
|
||
}
|
||
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "del pcm_stream queue succ.\r\n");
|
||
return;
|
||
}
|
||
|
||
static errcode_t pcm_stream_task_body(void *data)
|
||
{
|
||
UNUSED(data);
|
||
pcm_stream_queue_msg msg;
|
||
errcode_t res;
|
||
uint32_t msg_size = sizeof(pcm_stream_queue_msg);
|
||
|
||
if (memset_s(&msg, msg_size, 0, msg_size) != EOK) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "pcm stream message memset fail\r\n");
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
g_pcm_stream_end_record_sended_flag = false;
|
||
|
||
for (;;) {
|
||
osStatus_t ret = osMessageQueueGet(g_pcm_stream_msg_queue_id, &msg, nullptr, osWaitForever);
|
||
if (ret != osOK) {
|
||
msg.msg_id = MSGCENTER_TYPE_ID_XIAODU_END_RECORD;
|
||
msg.data = nullptr;
|
||
}
|
||
if (msg.msg_id == MSGCENTER_TYPE_ID_XIAODU_SEND_PCM_STREAM) {
|
||
res = msg_center_xiaodu_send_pcm_stream(MSGCENTER_CMD_XIAODU, MSGCENTER_TYPE_ID_XIAODU_SEND_PCM_STREAM,
|
||
msg.data, msg.len);
|
||
free(msg.data);
|
||
msg.data = nullptr;
|
||
if (res != ERRCODE_SUCC) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "send pcm stream failed");
|
||
pcm_stream_del_queue();
|
||
return ERRCODE_FAIL;
|
||
}
|
||
} else if (msg.msg_id == MSGCENTER_TYPE_ID_XIAODU_END_RECORD) {
|
||
res = msg_center_xiaodu_send_end_record(MSGCENTER_CMD_XIAODU, MSGCENTER_TYPE_ID_XIAODU_END_RECORD, msg.data,
|
||
msg.len);
|
||
free(msg.data);
|
||
msg.data = nullptr;
|
||
if (res != ERRCODE_SUCC) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "send pcm end failed");
|
||
pcm_stream_del_queue();
|
||
return ERRCODE_FAIL;
|
||
}
|
||
g_pcm_stream_end_record_sended_flag = true;
|
||
return ERRCODE_SUCC;
|
||
}
|
||
}
|
||
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
/*
|
||
异常场景时清除audio资源、pcm队列资源
|
||
可能的异常场景包括:
|
||
1)录音过程中,JS直接退出;
|
||
2)录音完成后,等待APP结果未返回时,JS退出;
|
||
*/
|
||
void msg_center_xiaodu_audio_pcm_clear_res(void)
|
||
{
|
||
OHOS::ACELite::AudioCapturerModule::ExceptionStop();
|
||
if (g_pcm_stream_end_record_sended_flag == false) {
|
||
pcm_stream_queue_msg msg;
|
||
msg.msg_id = MSGCENTER_TYPE_ID_XIAODU_END_RECORD;
|
||
msg.data = 0;
|
||
msg.len = 1;
|
||
if (g_pcm_stream_msg_queue_id != nullptr) {
|
||
osStatus_t ret = osMessageQueuePut(g_pcm_stream_msg_queue_id, &msg, 0, 0);
|
||
if (ret != osOK) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "Fatal err, ret = %d\r\n", ret);
|
||
}
|
||
WEARABLE_LOGD(WEARABLE_LOG_MODULE_MSG_CENTER, "active send pcm end\r\n");
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
osMessageQueueId_t GetPcmMsgQueueId(void)
|
||
{
|
||
return g_pcm_stream_msg_queue_id;
|
||
}
|
||
|
||
errcode_t pcm_stream_create_task(void)
|
||
{
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
ret = pcm_stream_task_init();
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
osThreadAttr_t attr = {"pcm_stream", 0, nullptr, 0, nullptr, PCM_STREAM_MSG_STACK_SIZE, TASK_PRIORITY_PCM_STREAM, 0,
|
||
0 };
|
||
if (osThreadNew((osThreadFunc_t)pcm_stream_task_body, nullptr, &attr) == nullptr) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "create pcm_stream task fail!\r\n");
|
||
pcm_stream_del_queue();
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "create pcm_stream task succ!\r\n");
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_start(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
unused(usr_data);
|
||
uint8_t ack = 1;
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
#if defined(SUPPORT_POWER_MANAGER)
|
||
const power_display_svr_api_t *display_api = power_display_svr_get_api();
|
||
if (display_api->get_screen_state() != SCREEN_ON) {
|
||
display_api->turn_on_screen();
|
||
}
|
||
display_api->set_screen_set_keepon_timeout(30000); // 30000ms
|
||
#endif
|
||
#ifdef JS_ENABLE
|
||
StartJsApp("com.vendor.voiceassistant");
|
||
#endif
|
||
|
||
/* ack */
|
||
ret = msg_center_send_data(cmd_id, type, &ack, sizeof(ack));
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_recv_xiaodu_info(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
uint8_t tl_len = msg_center_get_tlv_tl_len(usr_data);
|
||
uint16_t payload_len = usr_len - tl_len;
|
||
uint8_t *tlv_payload = (uint8_t *)msg_center_get_tlv_payload(usr_data);
|
||
uint8_t ack = 1;
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
/* ack */
|
||
ret = msg_center_send_data(cmd_id, type, &ack, sizeof(ack));
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
char *data = (char *)malloc(payload_len + 1);
|
||
if (data == nullptr) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "msg_center_xiaodu_recv_xiaodu_info: malloc failed.\r\n");
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
(void)memcpy_s(data, payload_len, tlv_payload, payload_len);
|
||
data[payload_len] = '\0';
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "recv xiaodu info--> %s\r\n", data);
|
||
DmsLiteSendMsgToJS(data);
|
||
free(data);
|
||
data = nullptr;
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_recv_wenxin_info(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
uint8_t tl_len = msg_center_get_tlv_tl_len(usr_data);
|
||
uint16_t payload_len = usr_len - tl_len;
|
||
uint8_t *tlv_payload = (uint8_t *)msg_center_get_tlv_payload(usr_data);
|
||
uint8_t ack = 1;
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
/* ack */
|
||
ret = msg_center_send_data(cmd_id, type, &ack, sizeof(ack));
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
char *data = (char *)malloc(payload_len + 1);
|
||
if (data == nullptr) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "msg_center_xiaodu_recv_wenxin_info: malloc failed.\r\n");
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
(void)memcpy_s(data, payload_len, tlv_payload, payload_len);
|
||
data[payload_len] = '\0';
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "recv wenxin info--> %s\r\n", data);
|
||
DmsLiteSendMsgToJS(data);
|
||
free(data);
|
||
data = nullptr;
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
static int32_t convert_para_to_player_para(const uint8_t *inParam, uint16_t paramLen, int32_t *outArgc,
|
||
uint8_t **outArgv)
|
||
{
|
||
int ret;
|
||
char *pos;
|
||
uint8_t *strTemp;
|
||
uint32_t paramCnt = 0;
|
||
|
||
strTemp = (uint8_t*)osal_kmalloc(paramLen, OSAL_GFP_KERNEL);
|
||
if (strTemp == nullptr) {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} malloc failed.\r\n", __FUNCTION__, __LINE__);
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
ret = memset_s(strTemp, paramLen, 0, paramLen);
|
||
if (ret != EOK) {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} memset_s failed.\r\n", __FUNCTION__, __LINE__);
|
||
osal_kfree(strTemp);
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
ret = memcpy_s(strTemp, paramLen, inParam, paramLen);
|
||
if (ret != EOK) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} memcpy_s failed.\r\n", __FUNCTION__, __LINE__);
|
||
osal_kfree(strTemp);
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
pos = strtok((char*)strTemp, ",");
|
||
for (uint32_t i = 0; pos != nullptr; i++) {
|
||
outArgv[i] = (uint8_t*)osal_kmalloc(strlen(pos) + 1, OSAL_GFP_KERNEL);
|
||
if (outArgv[i] == nullptr) {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} malloc failed.\r\n", __FUNCTION__, __LINE__);
|
||
osal_kfree(strTemp);
|
||
return ERRCODE_FAIL;
|
||
}
|
||
ret = memcpy_s(outArgv[i], strlen(pos) + 1, pos, strlen(pos) + 1);
|
||
if (ret != EOK) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} memcpy_s failed.\r\n", __FUNCTION__, __LINE__);
|
||
osal_kfree(strTemp);
|
||
return ERRCODE_FAIL;
|
||
}
|
||
paramCnt++;
|
||
if (*outArgc >= TTS_MEDIA_MAX_PARAM_CNT) {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} invalid argc: %d(max: 64).\r\n",
|
||
__FUNCTION__, __LINE__, *outArgc);
|
||
osal_kfree(strTemp);
|
||
return ERRCODE_FAIL;
|
||
}
|
||
pos = strtok(nullptr, ",");
|
||
}
|
||
|
||
*outArgc = paramCnt;
|
||
osal_kfree(strTemp);
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
static void msg_center_tts_player_start(const uint8_t *data, uint32_t dataLen)
|
||
{
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} func in.\r\n", __FUNCTION__, __LINE__);
|
||
|
||
int32_t argc = 0;
|
||
uint8_t *argv[TTS_MEDIA_MAX_PARAM_CNT];
|
||
int32_t ret = ERRCODE_FAIL;
|
||
|
||
ret = convert_para_to_player_para(data, dataLen, &argc, argv);
|
||
if (ret != ERRCODE_SUCC) {
|
||
goto FREE;
|
||
}
|
||
|
||
for (int32_t i = 0; i < argc; i++) {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} argv[%d]: %s\r\n", __FUNCTION__, __LINE__, i, argv[i]);
|
||
}
|
||
|
||
ret = PlayerSample(argc, (const char **)argv);
|
||
|
||
FREE:
|
||
for (int32_t i = 0; i < argc; i++) {
|
||
if (argv[i] != nullptr) {
|
||
osal_kfree(argv[i]);
|
||
argv[i] = nullptr;
|
||
}
|
||
}
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "{%s():%d} func out %s.\r\n", __FUNCTION__, __LINE__,
|
||
(ret == ERRCODE_SUCC) ? "success" : "failure");
|
||
return;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_recv_tts(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
uint8_t tl_len = msg_center_get_tlv_tl_len(usr_data);
|
||
uint16_t payload_len = usr_len - tl_len;
|
||
uint8_t *tlv_payload = (uint8_t *)msg_center_get_tlv_payload(usr_data);
|
||
uint8_t ack = 1;
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
/* ack */
|
||
ret = msg_center_send_data(cmd_id, type, &ack, sizeof(ack));
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
/* 播放tts语音 */
|
||
char *tts_file = (char *)malloc(payload_len + 1);
|
||
if (tts_file == nullptr) {
|
||
WEARABLE_LOGE(WEARABLE_LOG_MODULE_MSG_CENTER, "msg_center_xiaodu_recv_tts: malloc failed.\r\n");
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
(void)memcpy_s(tts_file, payload_len, tlv_payload, payload_len);
|
||
tts_file[payload_len] = '\0';
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "recv_tts file: %s\r\n", tts_file);
|
||
|
||
char buffer[TTS_AUDIO_PARA_LEN] = {0};
|
||
(void)sprintf_s(buffer, TTS_AUDIO_PARA_LEN, "%s,%s,%d,%d", "xx", tts_file, 1, 0);
|
||
msg_center_tts_player_start((const uint8_t *)buffer, strlen(buffer));
|
||
|
||
/* 播放完成后需删除文件 */
|
||
if (unlink(tts_file) < 0) {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "del tts_file fail.\r\n");
|
||
} else {
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "del tts_file succ.\r\n");
|
||
}
|
||
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_start_record(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
uint8_t start_flag = 1;
|
||
ret = msg_center_send_data(cmd_id, type, &start_flag, sizeof(start_flag));
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
|
||
errcode_t msg_center_xiaodu_send_pcm_stream(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
ret = msg_center_send_data(cmd_id, type, usr_data, usr_len);
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_send_end_record(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
ret = msg_center_send_data(cmd_id, type, usr_data, usr_len);
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "send pcm stream end, usr_data = %d, usr_len = %d\r\n",
|
||
*(uint8_t *)usr_data, usr_len); /* usr_data参考协议msg_center_pcm_end_flag_t */
|
||
pcm_stream_del_queue();
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
errcode_t msg_center_xiaodu_send_stop_answer(uint8_t cmd_id, uint8_t type, void *usr_data, uint16_t usr_len)
|
||
{
|
||
errcode_t ret = ERRCODE_SUCC;
|
||
|
||
ret = msg_center_send_data(cmd_id, type, usr_data, usr_len);
|
||
if (ret != ERRCODE_SUCC) {
|
||
return ERRCODE_FAIL;
|
||
}
|
||
|
||
WEARABLE_LOGI(WEARABLE_LOG_MODULE_MSG_CENTER, "send js exit msg, usr_data = %d, usr_len = %d\r\n",
|
||
*(uint8_t *)usr_data, usr_len); /* usr_data: 0 --normal exit, 1 -- abnormal exit */
|
||
return ERRCODE_SUCC;
|
||
}
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|