if (ret != 0)
{
ctx->stats.retryCount++;
- usleep(100000);
+ LOS_Msleep(100);
goto WRITE_RETRY;
}
ctx->stats.totalBytesPlayed += msg.size;
else
{
MEDIA_ERR_LOG("AudioStreamPlayThread: queue get error=%d", status);
- usleep(10000);
+ LOS_Msleep(100);
}
}
else
{
- usleep(10000);
+ LOS_Msleep(100);
}
}
{
if (handle == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerStart: handle is null");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStart: handle is null");
return -1;
}
if (ctx->state == AUDIO_STREAM_STATE_PLAYING)
{
- MEDIA_WARNING_LOG("AudioStreamPlayerStart: already playing");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStart: already playing");
return 0;
}
int32_t ret = AudioStreamOutPlay();
if (ret != 0)
{
- MEDIA_ERR_LOG("AudioStreamPlayerStart: failed to start audio stream, ret=%d", ret);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStart: failed to start audio stream, ret=%d", ret);
return -1;
}
errcode_t ret_errcode_t = uapi_create_osThread_custom(&task_cfg);
if (ret_errcode_t != ERRCODE_SUCC)
{
- MEDIA_ERR_LOG("AudioStreamPlayerStart: failed to create thread: %d", ret_errcode_t);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStart: failed to create thread: %d", ret_errcode_t);
ctx->isStopped = true;
ctx->state = AUDIO_STREAM_STATE_ERROR;
return -1;
{
if (handle == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerPause: handle is null");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerPause: handle is null");
return -1;
}
if (ctx->state != AUDIO_STREAM_STATE_PLAYING)
{
- MEDIA_WARNING_LOG("AudioStreamPlayerPause: not playing");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerPause: not playing");
return -1;
}
{
if (handle == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerResume: handle is null");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerResume: handle is null");
return -1;
}
if (ctx->state != AUDIO_STREAM_STATE_PAUSED)
{
- MEDIA_WARNING_LOG("AudioStreamPlayerResume: not paused");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerResume: not paused");
return -1;
}
{
if (handle == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerStop: handle is null");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStop: handle is null");
return -1;
}
if (ctx->state == AUDIO_STREAM_STATE_STOPPED)
{
- MEDIA_WARNING_LOG("AudioStreamPlayerStop: already stopped");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerStop: already stopped");
return 0;
}
{
if (handle == nullptr || data == nullptr || size == 0)
{
- MEDIA_ERR_LOG("AudioStreamPlayerWrite: invalid parameters");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerWrite: invalid parameters");
return -1;
}
if (ctx->state != AUDIO_STREAM_STATE_PLAYING && ctx->state != AUDIO_STREAM_STATE_PAUSED)
{
- MEDIA_ERR_LOG("AudioStreamPlayerWrite: player not in playing/paused state");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerWrite: player not in playing/paused state");
return -1;
}
uint8_t *dataCopy = (uint8_t *)malloc(size);
if (dataCopy == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerWrite: failed to allocate memory");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerWrite: failed to allocate memory");
return -1;
}
msg.size = size;
msg.timestamp = (uint32_t)time(nullptr);
- osStatus_t status = osMessageQueuePut(ctx->inputQueue, &msg, 0, 0);
- if (status == osOK)
+ osStatus_t status;
+ const uint32_t put_timeout_ms = 50; //单次等待上限
+ int retries = 6; // 总等待 ~300ms
+ do
{
- ctx->queueMsgCount++;
- ctx->stats.queueCurrentSize = ctx->queueMsgCount;
- MEDIA_DEBUG_LOG("AudioStreamPlayerWrite: queued %u bytes", size);
- return 0;
- }
- else
- {
- MEDIA_WARNING_LOG("AudioStreamPlayerWrite: queue full or error=%d, dropping frame", status);
- ctx->stats.droppedFrames++;
- free(dataCopy);
- return -1;
- }
+ status = osMessageQueuePut(ctx->inputQueue, &msg, 0, put_timeout_ms);
+ if (status == osOK)
+ {
+ ctx->queueMsgCount++;
+ ctx->stats.queueCurrentSize = ctx->queueMsgCount;
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerWrite: queued %u bytes", size);
+ return 0;
+ }
+ LOS_Msleep(10); // 10ms 小憩等待消费
+ } while (--retries > 0);
+ // 超过重试仍满,丢弃本块
+ ctx->stats.droppedFrames++;
+ free(dataCopy);
+ return -1;
}
// 清空播放队列
{
if (handle == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerFlush: handle is null");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerFlush: handle is null");
return -1;
}
{
if (handle == nullptr || stats == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerGetStats: invalid parameters");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerGetStats: invalid parameters");
return -1;
}
{
if (handle == nullptr || volume < 0.0f || volume > 1.0f)
{
- MEDIA_ERR_LOG("AudioStreamPlayerSetVolume: invalid parameters");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerSetVolume: invalid parameters");
return -1;
}
{
if (handle == nullptr)
{
- MEDIA_ERR_LOG("AudioStreamPlayerDestroy: handle is null");
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"AudioStreamPlayerDestroy: handle is null");
return -1;
}
cfg.channels = 1;
cfg.bitsPerSample = 16;
cfg.bufferSize = 2048;
- cfg.queueSize = 10;
+ cfg.queueSize = 32;
if (AudioStreamPlayerCreate(&cfg, &g_ln_audio_player) != 0) {
printf("[LN_AUDIO] create failed\n");
return AudioStreamPlayerWrite(g_ln_audio_player, data, size);
}
+int32_t ln_audio_player_get_stats(AudioStreamStats* stats)
+{
+ if (stats == nullptr) return -1;
+ if (g_ln_audio_player == nullptr) return -1;
+ return AudioStreamPlayerGetStats(g_ln_audio_player, stats);
+}
+
#ifdef __cplusplus
};
#endif
\ No newline at end of file
uint32_t ln_audio_player_init(void);
int32_t ln_audio_player_write(const uint8_t* data, uint32_t size);
+int32_t ln_audio_player_get_stats(AudioStreamStats* stats);
#ifdef __cplusplus
}
//获取设备Token
static uint32_t ln_get_device_token_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
VAD_UNUSED(strCommonCmd);
- uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
- uint32_t argc = 0;
- (void)ConvertCmdToParam(para, paraLen, argv, &argc);
-
- const char *device_id = (argc >= 1) ? (const char *)argv[0] : uapi_ln_get_device_id();
- const char *device_iccid = (argc >= 2) ? (const char *)argv[1] : uapi_ln_get_device_iccid();
- const char *device_model = (argc >= 3) ? (const char *)argv[2] : uapi_ln_get_device_model();
- const char *device_ver = (argc >= 4) ? (const char *)argv[3] : uapi_ln_get_device_version();
- printf("[LN] GetDeviceToken start id=%s iccid=%s model=%s ver=%s\n", device_id, device_iccid, device_model, device_ver);
- ln_device_token_req_t req = {0};
- strcpy(req.device_id, device_id);
- strcpy(req.device_iccid, device_iccid);
- strcpy(req.device_model, device_model);
- strcpy(req.device_version, device_ver);
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN, (char *)&req, sizeof(req));
+ do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN, NULL, 0);
return ERRCODE_SUCC;
}
static uint32_t ln_speech_chat_stream_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
VAD_UNUSED(strCommonCmd);
- uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
- uint32_t argc = 0;
- (void)ConvertCmdToParam(para, paraLen, argv, &argc);
-
- const char *device_id = uapi_ln_get_device_id();
- const char *device_token = uapi_ln_get_device_token();
- if((device_id == NULL) || (device_token == NULL))
- {
- printf("[LN] SpeechChat device_id or device_token is NULL\n");
- return ERRCODE_SUCC;
- }
- const char *audio_path = "/user/test_audio.mp3";
-
- ln_speech_chat_req_t req = {0};
- strncpy(req.device_id, device_id, sizeof(req.device_id) - 1);
- strncpy(req.device_token, device_token, sizeof(req.device_token) - 1);
- strncpy(req.audio_path, audio_path, sizeof(req.audio_path) - 1);
-
- printf("[LN] SpeechChat submit: id=%s\n", req.device_id);
- printf("[LN] SpeechChat submit: token=%s\n", req.device_token);
- printf("[LN] SpeechChat submit: audio=%s\n", req.audio_path);
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM, (char *)&req, sizeof(req));
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM, NULL, 0);
return ERRCODE_SUCC;
}
static uint32_t ln_story_choose_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
VAD_UNUSED(strCommonCmd);
- uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0}; uint32_t argc = 0; (void)ConvertCmdToParam(para, paraLen, argv, &argc);
- const char *audio_path = (argc >= 1) ? (const char *)argv[0] : "/user/story_request.mp3";
- ln_story_choose_req_t req = {0}; strncpy(req.audio_path, audio_path, sizeof(req.audio_path) - 1);
- printf("[LN][STORY_CHOOSE] audio=%s\n", req.audio_path);
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_STORY_CHOOSE, (char *)&req, sizeof(req));
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_STORY_CHOOSE, NULL, 0);
return ERRCODE_SUCC;
}
/* 故事-获取退出哄睡询问:AT^LN_STORY_EXIT */
static uint32_t ln_story_exit_inquiry_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][STORY_EXIT_INQUIRY]\n");
do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_STORY_EXIT_INQUIRY, NULL, 0);
return ERRCODE_SUCC;
/* 故事-确认结束哄睡模式:AT^LN_STORY_FINISH */
static uint32_t ln_story_finish_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][STORY_FINISH]\n");
do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_STORY_FINISH, NULL, 0);
return ERRCODE_SUCC;
/* 设备-获取角色信息:AT^LN_DEV_CHARACTER */
static uint32_t ln_device_get_character_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][DEVICE_GET_CHARACTER]\n");
do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_CHARACTER, NULL, 0);
return ERRCODE_SUCC;
/* 设备-获取绑定用户ID:AT^LN_DEV_USERID */
static uint32_t ln_device_get_userid_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][DEVICE_GET_USER_ID]\n");
do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_USER_ID, NULL, 0);
return ERRCODE_SUCC;
/* OTA-获取升级任务:AT^LN_OTA_GET_TASK */
static uint32_t ln_ota_get_task_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][OTA_GET_TASK]\n");
do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, NULL, 0);
return ERRCODE_SUCC;
*/
static uint32_t ln_ota_download_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][OTA_DOWNLOAD]\n");
do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD, NULL, 0);
return ERRCODE_SUCC;
/* AT^LN_WS_START */
static uint32_t ln_ws_start_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
{
- VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd);
+ VAD_UNUSED(para);
+ VAD_UNUSED(paraLen);
+ VAD_UNUSED(strCommonCmd);
printf("[LN][WS_START]\n");
int ret = ln_ws_start();
if (ret != 0)
return (g_ln_last_saved_path[0] != '\0') ? g_ln_last_saved_path : NULL;
}
+/* 获取语音对话流录音音频路径 */
+const char *uapi_ln_get_speechchat_audio_path(void)
+{
+ return "/user/leiniao/speech_chat_audio.mp3";
+}
+/* 获取选择故事录音音频路径 */
+const char *uapi_ln_get_story_choose_audio_path(void)
+{
+ return "/user/leiniao/story_choose_audio.mp3";
+}
/* 自适应申请HttpClient缓冲(保证header>=2048),失败则逐步扩容重试 */
HTTPC_RESULT ln_http_prepare_auto(HttpClientData *clientData, int header_size, int resp_size)
{
int ret = -1;
size_t total_written = 0;
+ #if TEST_MP3_DOWNLOAD
// 打开文件准备写入
FILE *fd = fopen(save_path, "wb");
if (!fd)
printf("[SSE] fopen failed for %s\n", save_path);
return ERRCODE_FAIL;
}
+ #endif
HTTPC_RESULT prep = ln_http_prepare_auto(&client_data, 2048, LN_CLIENT_PREPARE_SIZE * 2);
if (prep != HTTP_SUCCESS)
{
printf("[SSE] prepare failed: %d\n", prep);
+ #if TEST_MP3_DOWNLOAD
fclose(fd);
+ #endif
return ERRCODE_FAIL;
}
if (ret != 0)
{
printf("[SSE] connection failed, ret=0x%x\n", ret);
+ #if TEST_MP3_DOWNLOAD
fclose(fd);
+ #endif
HttpClientUnprepare(&client_data);
return ERRCODE_FAIL;
}
if (ret != 0)
{
printf("[SSE] send request failed, ret=0x%x\n", ret);
+ #if TEST_MP3_DOWNLOAD
fclose(fd);
+ #endif
HttpClientClse(&client);
HttpClientUnprepare(&client_data);
return ERRCODE_FAIL;
{
if (client_data.contentBlockLen > 0)
{
+ #if TEST_MP3_DOWNLOAD
/* 一边下载到文件,一边推送到播放器队列,尝试边下边播 */
size_t written = fwrite(client_data.responseBuf, 1, client_data.contentBlockLen, fd);
if (written != client_data.contentBlockLen)
HttpClientUnprepare(&client_data);
return ERRCODE_FAIL;
}
+ total_written += written;
+ #endif
/* 非阻塞入队,队列满则忽略该块 */
(void)ln_audio_player_write((const uint8_t*)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
- total_written += written;
}
}
else
}
} while (client_data.isMore);
+ #if TEST_MP3_DOWNLOAD
fclose(fd);
+ #endif
HttpClientUnprepare(&client_data);
HttpClientClse(&client);
}
if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN)
{
- if (mail.data != NULL && mail.len == sizeof(ln_device_token_req_t))
- {
- printf("LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN:获取雷鸟设备Token\n");
- ln_device_token_req_t req;
- memcpy(&req, mail.data, sizeof(req));
- ln_get_device_token_http(req.device_id, req.device_iccid, req.device_model, req.device_version);
- }
+ printf("LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN:获取雷鸟设备Token\n");
+ ln_get_device_token_http(uapi_ln_get_device_id(), uapi_ln_get_device_iccid(), uapi_ln_get_device_model(), uapi_ln_get_device_version());
}
else if (mail.cmd == LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM)
{
- if (mail.data != NULL && mail.len == sizeof(ln_speech_chat_req_t))
- {
- printf("LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM\n");
- ln_speech_chat_req_t req;
- memcpy(&req, mail.data, sizeof(req));
- ln_speech_chat_stream_http(req.device_id, req.device_token, req.audio_path);
- }
+ printf("LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM\n");
+ ln_speech_chat_stream_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_speechchat_audio_path());
}
else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_CHOOSE)
{
- if (mail.data && mail.len == sizeof(ln_story_choose_req_t)) {
- printf("LN_HTTP_SERVICE_CMD_STORY_CHOOSE:选择故事\n");
- ln_story_choose_req_t req; memcpy(&req, mail.data, sizeof(req));
- ln_story_choose_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.audio_path);
- }
+ printf("LN_HTTP_SERVICE_CMD_STORY_CHOOSE:选择故事\n");
+ ln_story_choose_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_story_choose_audio_path());
}
else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_RANDOM)
{
- if (mail.data && mail.len == sizeof(ln_story_random_req_t)) {
+ if (mail.data && mail.len == sizeof(ln_story_random_req_t))
+ {
printf("LN_HTTP_SERVICE_CMD_STORY_RANDOM:随机故事\n");
ln_story_random_req_t req; memcpy(&req, mail.data, sizeof(req));
ln_story_random_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.story_theme[0] ? req.story_theme : NULL);
#define LN_DATA_PATH "/user/leiniao"
#define LN_CLIENT_PREPARE_SIZE 2*1024
+#define TEST_MP3_DOWNLOAD 0 //测试下载mp3
#define LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN 0x1 /* 获取设备 token */
#define LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM 0x2 /* 语音对话流 */
#define LN_HTTP_SERVICE_CMD_AUDIO_PAUSE 0x1005 /* 暂停播放 */
#define LN_HTTP_SERVICE_CMD_AUDIO_RESUME 0x1006 /* 恢复播放 */
-typedef struct
-{
- char device_id[64];
- char device_iccid[32];
- char device_model[32];
- char device_version[16];
-} ln_device_token_req_t;
-
-typedef struct
-{
- char device_id[64];
- char device_token[512];
- char audio_path[256];
-} ln_speech_chat_req_t;
-
-/* 故事-选择故事 请求体 */
-typedef struct
-{
- char audio_path[256];
-} ln_story_choose_req_t;
-
/* 故事-随机故事 请求体(可选主题)*/
typedef struct
{
int uapi_ln_ota_get_update_type(void);
/* OTA 下载保存的最后一个文件路径(无则返回NULL)*/
const char *uapi_ln_ota_get_saved_path(void);
+/* 获取语音对话流录音音频路径 */
+const char *uapi_ln_get_speechchat_audio_path(void);
+/* 获取选择故事录音音频路径 */
+const char *uapi_ln_get_story_choose_audio_path(void);
/* ============================== 共享全局状态(跨文件) ============================== */
extern char *g_device_token;