From e1de3d396032065525f247e1cd3e249134532fd5 Mon Sep 17 00:00:00 2001 From: cheng Date: Sat, 13 Sep 2025 16:32:51 +0800 Subject: [PATCH] =?utf8?q?=E5=AE=9E=E7=8E=B0mp3=E7=9A=84=E9=A1=BA=E5=BA=8F?= =?utf8?q?=E6=92=AD=E6=94=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../wearable/fd230/nativeapp/CMakeLists.txt | 1 + .../leiniao/include/ln_story_player_simple.h | 93 +++ .../leiniao/src/ln_story_player_simple.cpp | 550 ++++++++++++++++++ .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 21 + code/sdk/zhihui/leiniao/imsl_ln/ln_api.c | 41 +- code/sdk/zhihui/leiniao/imsl_ln/ln_api.h | 7 +- 6 files changed, 707 insertions(+), 6 deletions(-) create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/include/ln_story_player_simple.h create mode 100644 code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/src/ln_story_player_simple.cpp diff --git a/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt b/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt index 76dac27e4..172bcd83c 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt +++ b/code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt @@ -76,6 +76,7 @@ set(PRIVATE_HEADER ${ROOT_DIR}/zhihui/4g/cat1Service/include ${ROOT_DIR}/zhihui/4g/cat1Service/Service ${ROOT_DIR}/zhihui/ai/include/ + ${ROOT_DIR}/zhihui/leiniao/imsl_ln/ #暂时添加 ) diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/include/ln_story_player_simple.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/include/ln_story_player_simple.h new file mode 100644 index 000000000..b558268c9 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/include/ln_story_player_simple.h @@ -0,0 +1,93 @@ +#ifndef LN_STORY_PLAYER_SIMPLE_H +#define LN_STORY_PLAYER_SIMPLE_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" +{ +#endif +#endif + +#include "stdint.h" +#include "errcode.h" +#include + +/* ============================== 精简版故事播放器接口 ============================== */ + +/** + * @brief 开始播放指定目录下的音频文件(顺序播放) + * @param story_dir 故事文件目录路径 + * @return true 成功,false 失败 + * + * 功能说明: + * - 自动扫描目录下的音频文件(支持mp3, wav, aac, m4a格式) + * - 按文件名顺序播放所有音频文件 + * - 播放完一个文件后自动播放下一个文件 + * - 音频系统只初始化一次,提高效率 + */ +bool ln_story_player_simple_start(const char *story_dir); + +/** + * @brief 停止播放并清理所有资源 + * @return 无返回值 + * + * 功能说明: + * - 立即停止当前播放 + * - 清理所有音频资源 + * - 重置播放器状态 + */ +void ln_story_player_simple_stop(void); + +/** + * @brief 检查是否正在播放 + * @return true 正在播放,false 未播放 + */ +bool ln_story_player_simple_is_playing(void); + +/** + * @brief 获取当前播放的文件索引 + * @return 当前播放的文件索引(从0开始),-1表示未播放 + */ +int ln_story_player_simple_get_current_index(void); + +/** + * @brief 获取总文件数 + * @return 扫描到的音频文件总数 + */ +int ln_story_player_simple_get_file_count(void); + +/** + * @brief 处理播放器消息队列命令(内部使用) + * @param cmd 命令类型 + * @param data 数据指针 + * @param len 数据长度 + */ +void ln_story_player_simple_handle_message(int cmd, char *data, uint32_t len); + +/* ============================== 使用示例 ============================== */ + +/* +// 开始播放 +if (ln_story_player_simple_start("/user/leiniao/story/choose")) +{ + printf("播放开始成功\n"); +} + +// 检查播放状态 +if (ln_story_player_simple_is_playing()) +{ + printf("正在播放第 %d 个文件,共 %d 个文件\n", + ln_story_player_simple_get_current_index(), + ln_story_player_simple_get_file_count()); +} + +// 停止播放 +ln_story_player_simple_stop(); +*/ + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/src/ln_story_player_simple.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/src/ln_story_player_simple.cpp new file mode 100644 index 000000000..4a0a22fd3 --- /dev/null +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/leiniao/src/ln_story_player_simple.cpp @@ -0,0 +1,550 @@ +#include "leiniao/include/ln_story_player_simple.h" +#include +#include +#include +#include +#include +#include +#include +#include +/* 引入播放器相关头文件 */ +#include "player.h" +#include "source.h" +#include "audio_manager.h" +#include +#include +#include +#include +/* 引入消息队列相关头文件 */ +#include "ln_api.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +using OHOS::Media::Player; +using OHOS::Media::Source; +using namespace OHOS::Media; +using namespace::Audio; +using Audio::AudioManager; + +/* ============================== 精简版播放器结构体 ============================== */ + +/* 播放器消息命令定义 */ + + +typedef struct +{ + /* 文件列表 */ + char file_paths[100][256]; // 最多100个文件 + int file_count; + int current_index; + + /* 播放器对象 */ + std::shared_ptr player; + std::shared_ptr source; + std::map header; + + /* 音频管理 */ + AudioSession sessionId; + std::shared_ptr interrupt; + std::shared_ptr interruptListener; + bool audio_initialized; + bool is_activate_audio_interrupt; // 音频中断激活标志 + + /* 状态标志 */ + bool is_playing; + bool should_stop; +} ln_story_player_simple_t; + + +static bool ln_story_player_simple_play_file(ln_story_player_simple_t *impl, int file_index); + +/* ============================== 播放器回调类 ============================== */ + +class SimplePlayerCallback : public PlayerCallback +{ +public: + SimplePlayerCallback(ln_story_player_simple_t *impl) : impl_(impl) {} + + void OnPlaybackComplete() override + { + if (impl_ && !impl_->should_stop) + { + printf("[SIMPLE_PLAYER] playback completed, scheduling next file\n"); + // 通过消息队列播放下一个文件,避免在回调中直接调用 + impl_->current_index++; + if (impl_->current_index < impl_->file_count) + { + // 发送消息到 ln_http_server_send_task 线程 + do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT, NULL, 0); + } + else + { + printf("[SIMPLE_PLAYER] all files played, stopping(所有文件播放完成)\n"); + impl_->is_playing = false; + } + } + } + + void OnError(int32_t errorType, int32_t errorCode) override + { + printf("[SIMPLE_PLAYER] playback error: type=%d, code=%d\n", errorType, errorCode); + if (impl_) + { + impl_->is_playing = false; + } + } + + void OnInfo(int32_t type, int32_t extra) override {} + void OnRewindToComplete() override {} + +private: + ln_story_player_simple_t *impl_; +}; + +/* ============================== 中断监听器类 ============================== */ + +class SimplePlayerInterruptListener : public InterruptListener +{ +public: + SimplePlayerInterruptListener(ln_story_player_simple_t *impl) : impl_(impl) {} + + void OnInterrupt(int32_t type, int32_t hint) override + { + if (!impl_) + return; + + printf("[SIMPLE_PLAYER] OnInterrupt: type=%d, hint=%d\n", type, hint); + + if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE) + { + if (impl_->is_playing && impl_->player) + { + impl_->player->Pause(); + } + } + else if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME) + { + if (impl_->is_playing && impl_->player) + { + impl_->player->Play(); + } + } + else if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP) + { + if (impl_->is_playing) + { + impl_->player->Stop(); + impl_->is_playing = false; + } + } + } + +private: + ln_story_player_simple_t *impl_; +}; + +/* ============================== 全局变量 ============================== */ + +static ln_story_player_simple_t g_simple_player = {0}; +static std::shared_ptr g_player_callback = nullptr; +static std::shared_ptr g_interrupt_listener = nullptr; + +/* ============================== 内部函数 ============================== */ + +// 处理播放器消息队列命令 +void ln_story_player_simple_handle_message(int cmd, char *data, uint32_t len) +{ + if (cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT) + { + printf("[SIMPLE_PLAYER] received play next command\n"); + if (g_simple_player.is_playing && !g_simple_player.should_stop) + { + if (g_simple_player.current_index < g_simple_player.file_count) + { + ln_story_player_simple_play_file(&g_simple_player, g_simple_player.current_index); + } + } + } +} + +// 音频初始化(只初始化一次) +static bool AudioInit(void) +{ + if (g_simple_player.audio_initialized) + { + return true; + } + + AudioManager& amInstance = AudioManager::GetInstance(); + if (!amInstance.Initialize()) + { + printf("[SIMPLE_PLAYER] AudioManager Initialize failed\n"); + return false; + } + + g_simple_player.player = std::make_shared(); + if (!g_simple_player.player) + { + printf("[SIMPLE_PLAYER] Player create failed\n"); + return false; + } + + g_player_callback = std::make_shared(&g_simple_player); + if (!g_player_callback) + { + printf("[SIMPLE_PLAYER] PlayerCallback create failed\n"); + return false; + } + + g_simple_player.audio_initialized = true; + g_simple_player.is_activate_audio_interrupt = false; + + printf("[SIMPLE_PLAYER] Audio initialized successfully\n"); + return true; +} + +// 比较函数,用于文件名排序 +static int CompareFileNames(const void *a, const void *b) +{ + const char *file_a = (const char *)a; + const char *file_b = (const char *)b; + + // 提取文件名(去掉路径) + const char *name_a = strrchr(file_a, '/'); + const char *name_b = strrchr(file_b, '/'); + + if (name_a) name_a++; + else name_a = file_a; + if (name_b) name_b++; + else name_b = file_b; + + // 提取数字部分进行比较 + int num_a = atoi(name_a); + int num_b = atoi(name_b); + + return num_a - num_b; +} + +// 扫描目录获取音频文件 +static bool ScanAudioFiles(const char *story_dir) +{ + printf("[SIMPLE_PLAYER] scanning directory: %s\n", story_dir); + + // 检查目录是否存在 + if (access(story_dir, F_OK) == -1) + { + printf("[SIMPLE_PLAYER] directory does not exist: %s\n", story_dir); + return false; + } + + DIR *dir = opendir(story_dir); + if (!dir) + { + printf("[SIMPLE_PLAYER] failed to open directory: %s\n", story_dir); + return false; + } + + g_simple_player.file_count = 0; + struct dirent *entry; + + while ((entry = readdir(dir)) != NULL && g_simple_player.file_count < 100) + { + // 跳过 . 和 .. 目录 + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + { + continue; + } + + // 检查是否是音频文件 + const char *ext = strrchr(entry->d_name, '.'); + if (ext && (strcasecmp(ext, ".mp3") == 0 || strcasecmp(ext, ".wav") == 0 || + strcasecmp(ext, ".aac") == 0 || strcasecmp(ext, ".m4a") == 0)) + { + snprintf(g_simple_player.file_paths[g_simple_player.file_count], + sizeof(g_simple_player.file_paths[g_simple_player.file_count]), + "%s/%s", story_dir, entry->d_name); + g_simple_player.file_count++; + printf("[SIMPLE_PLAYER] found audio file: %s\n", entry->d_name); + } + } + + closedir(dir); + + // 对文件路径进行排序(按文件名中的数字排序) + if (g_simple_player.file_count > 1) + { + qsort(g_simple_player.file_paths, g_simple_player.file_count, + sizeof(g_simple_player.file_paths[0]), CompareFileNames); + printf("[SIMPLE_PLAYER] files sorted by name\n"); + } + + printf("[SIMPLE_PLAYER] found %d audio files\n", g_simple_player.file_count); + return g_simple_player.file_count > 0; +} + +// 播放指定文件 +static bool ln_story_player_simple_play_file(ln_story_player_simple_t *impl, int file_index) +{ + if (file_index < 0 || file_index >= impl->file_count) + { + printf("[SIMPLE_PLAYER] invalid file index: %d\n", file_index); + return false; + } + + printf("[SIMPLE_PLAYER] playing file %d: %s\n", file_index, impl->file_paths[file_index]); + + // 检查播放器状态 + int32_t player_state; + impl->player->GetPlayerState(player_state); + printf("[SIMPLE_PLAYER] current player state: %d\n", player_state); + + // 根据播放器状态进行处理 + if (player_state == PLAYER_STARTED || player_state == PLAYER_PLAYBACK_COMPLETE) + { + printf("[SIMPLE_PLAYER] stopping and resetting player\n"); + impl->player->Stop(); + impl->player->Reset(); + } + else if (player_state == PLAYER_PAUSED || player_state == PLAYER_IDLE) + { + printf("[SIMPLE_PLAYER] resetting player\n"); + impl->player->Reset(); + } + else + { + printf("[SIMPLE_PLAYER] unknown state, forcing reset\n"); + impl->player->Stop(); + impl->player->Reset(); + } + + // 设置回调函数 + g_simple_player.player->SetPlayerCallback(g_player_callback); + + // 设置音频源 + impl->source = std::make_shared(impl->file_paths[file_index], impl->header); + if (!impl->source) + { + printf("[SIMPLE_PLAYER] failed to create source\n"); + return false; + } + + int32_t ret = impl->player->SetSource(*impl->source); + if (ret != 0) + { + printf("[SIMPLE_PLAYER] set source failed: %d\n", ret); + impl->player->Reset(); + return false; + } + + // 配置播放器 + impl->player->SetAudioStreamType(AUDIO_STREAM_MUSIC); + + // 准备播放 + ret = impl->player->Prepare(); + if (ret != 0) + { + printf("[SIMPLE_PLAYER] prepare failed: %d\n", ret); + impl->player->Reset(); + return false; + } + + // 设置音频会话和中断监听 + AudioManager &amInstance = AudioManager::GetInstance(); + + // 如果已经激活过音频中断,先清理 + if (impl->is_activate_audio_interrupt && impl->interrupt && impl->sessionId != AUDIO_SESSION_ID_NONE) + { + amInstance.DeactivateAudioInterrupt(*impl->interrupt); + impl->is_activate_audio_interrupt = false; + printf("[SIMPLE_PLAYER] previous audio interrupt deactivated\n"); + } + + // 创建新的会话和中断 + impl->sessionId = amInstance.MakeSessionId(); + if (impl->sessionId == AUDIO_SESSION_ID_NONE) + { + printf("[SIMPLE_PLAYER] failed to create session\n"); + impl->player->Reset(); + return false; + } + + impl->interruptListener = std::make_shared(impl); + impl->interrupt = std::make_shared(); + impl->interrupt->streamType = AUDIO_STREAM_MUSIC; + impl->interrupt->sessionID = impl->sessionId; + impl->interrupt->interruptListener = impl->interruptListener; + + if (amInstance.ActivateAudioInterrupt(*impl->interrupt) == INTERRUPT_FAILED) + { + printf("[SIMPLE_PLAYER] failed to activate audio interrupt\n"); + impl->player->Reset(); + return false; + } + + impl->is_activate_audio_interrupt = true; + printf("[SIMPLE_PLAYER] audio interrupt activated for file %d\n", file_index); + + // 设置音频会话ID + ret = impl->player->SetAudioSessionId(impl->sessionId); + if (ret != 0) + { + printf("[SIMPLE_PLAYER] SetAudioSessionId failed: %d\n", ret); + impl->player->Reset(); + amInstance.DeactivateAudioInterrupt(*impl->interrupt); + return false; + } + + // 开始播放 + ret = impl->player->Play(); + if (ret != 0) + { + printf("[SIMPLE_PLAYER] play failed: %d\n", ret); + impl->player->Stop(); + impl->player->Reset(); + amInstance.DeactivateAudioInterrupt(*impl->interrupt); + return false; + } + + impl->is_playing = true; + printf("[SIMPLE_PLAYER] started playing file %d\n", file_index); + return true; +} + +// 清理音频中断 +static void ClearActivateAudioInterrupt(void) +{ + if (g_simple_player.is_activate_audio_interrupt && g_simple_player.interrupt && g_simple_player.sessionId != AUDIO_SESSION_ID_NONE) + { + AudioManager &amInstance = AudioManager::GetInstance(); + amInstance.DeactivateAudioInterrupt(*g_simple_player.interrupt); + g_simple_player.is_activate_audio_interrupt = false; + printf("[SIMPLE_PLAYER] audio interrupt cleared\n"); + } +} + +// 清理资源 +static void CleanupResources(void) +{ + if (g_simple_player.player) + { + g_simple_player.player->Stop(); + g_simple_player.player->Reset(); + g_simple_player.player->Release(); + g_simple_player.player.reset(); + } + + if (g_simple_player.is_activate_audio_interrupt && g_simple_player.interrupt && g_simple_player.sessionId != AUDIO_SESSION_ID_NONE) + { + AudioManager &amInstance = AudioManager::GetInstance(); + amInstance.DeactivateAudioInterrupt(*g_simple_player.interrupt); + g_simple_player.is_activate_audio_interrupt = false; + printf("[SIMPLE_PLAYER] audio interrupt deactivated\n"); + } + + g_simple_player.interrupt.reset(); + g_simple_player.interruptListener.reset(); + g_player_callback.reset(); + + memset(&g_simple_player, 0, sizeof(g_simple_player)); + printf("[SIMPLE_PLAYER] resources cleaned up\n"); +} + +/* ============================== 公共接口 ============================== */ + +// 开始播放指定目录下的音频文件(顺序播放) +bool ln_story_player_simple_start(const char *story_dir) +{ + if (!story_dir) + { + printf("[SIMPLE_PLAYER] invalid story directory\n"); + return false; + } + + printf("[SIMPLE_PLAYER] starting playback: %s\n", story_dir); + + // 如果已经在播放,先停止 + if (g_simple_player.is_playing) + { + printf("[SIMPLE_PLAYER] stopping playback\n"); + ln_story_player_simple_stop(); + } + + // 初始化音频(只初始化一次) + if (!AudioInit()) + { + printf("[SIMPLE_PLAYER] audio init failed\n"); + return false; + } + + // 扫描音频文件 + if (!ScanAudioFiles(story_dir)) + { + printf("[SIMPLE_PLAYER] no audio files found\n"); + return false; + } + + // 开始播放第一个文件 + g_simple_player.current_index = 0; + g_simple_player.should_stop = false; + + if (!ln_story_player_simple_play_file(&g_simple_player, 0)) + { + printf("[SIMPLE_PLAYER] failed to start playing\n"); + return false; + } + + printf("[SIMPLE_PLAYER] playback started successfully\n"); + return true; +} + +// 停止播放并清理资源 +void ln_story_player_simple_stop(void) +{ + printf("[SIMPLE_PLAYER] stopping playback\n"); + + g_simple_player.should_stop = true; + g_simple_player.is_playing = false; + + if (g_simple_player.player) + { + g_simple_player.player->Stop(); + g_simple_player.player->Reset(); + } + + // 清理音频中断 + ClearActivateAudioInterrupt(); + + // 清理资源 + CleanupResources(); + + printf("[SIMPLE_PLAYER] playback stopped\n"); +} + +// 检查是否正在播放 +bool ln_story_player_simple_is_playing(void) +{ + return g_simple_player.is_playing; +} + +// 获取当前播放的文件索引 +int ln_story_player_simple_get_current_index(void) +{ + return g_simple_player.current_index; +} + +// 获取总文件数 +int ln_story_player_simple_get_file_count(void) +{ + return g_simple_player.file_count; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __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 5564caa99..0ca99aa5c 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -636,6 +636,24 @@ static uint32_t ln_ota_download_at(uint8_t *para, uint32_t paraLen, char *strCom return ERRCODE_SUCC; } +/* 音频播放: AT^LN_STORY_PLAY_NEXT */ +static uint32_t ln_audio_play_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd); + printf("[LN][AUDIO_PLAY]\n"); + do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_AUDIO_PLAY, NULL, 0); + return ERRCODE_SUCC; +} + +/* 音频停止: AT^LN_STORY_PLAY_PREV */ +static uint32_t ln_audio_stop_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd); + printf("[LN][AUDIO_STOP]\n"); + do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_AUDIO_STOP, NULL, 0); + return ERRCODE_SUCC; +} + static const at_cmd_table_t g_ln_api_cmd[] = { /* ----------------------------------- VAD ---------------------------------- */ @@ -660,6 +678,9 @@ static const at_cmd_table_t g_ln_api_cmd[] = { {(char *)"AT^LN_DEV_USERID", ln_device_get_userid_at, (char *)"获取设备绑定用户ID(JSON,GET): AT^LN_DEV_USERID"}, {(char *)"AT^LN_OTA_GET_TASK", ln_ota_get_task_at, (char *)"获取OTA升级任务(JSON,GET): AT^LN_OTA_GET_TASK"}, {(char *)"AT^LN_OTA_DOWNLOAD", ln_ota_download_at, (char *)"下载OTA升级包(JSON,GET->下载): AT^LN_OTA_DOWNLOAD"}, + /* 音频播放 */ + {(char *)"AT^LN_STORY_PLAY_AT", ln_audio_play_at, (char *)"播放音频: AT^LN_STORY_PLAY_AT"}, + {(char *)"AT^LN_STORY_STOP_AT", ln_audio_stop_at, (char *)"停止播放音频: AT^LN_STORY_STOP_AT"}, }; at_cmd_table_t *get_leiniao_api_cmd_table(uint32_t *cmd_count) diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c index 971e3ac68..0f1d47ae4 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c @@ -12,9 +12,16 @@ #include #include "stdio.h" +#ifdef BOARD_N9 +#include "leiniao/include/ln_story_player_simple.h" +#endif + +// 声明播放器消息处理函数 +extern void ln_story_player_simple_handle_message(int cmd, char *data, uint32_t len); + static app_task_definition_t ln_send_taskcfg = {0}; static app_task_definition_t ln_recv_taskcfg = {0}; -#define LN_HTTP_BOARD_TASK_SIZE 0x4000 +#define LN_HTTP_BOARD_TASK_SIZE 0x3000 static unsigned long g_ln_send_queue = 0xFFFFFFFF; static unsigned long g_ln_recv_queue = 0xFFFFFFFF; @@ -441,6 +448,30 @@ static void ln_http_server_send_task(void const *arg) printf("LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD:下载OTA升级包\n"); ln_ota_download_flow_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_device_version()); } + else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY) + { + printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY:播放音频\n"); + #ifdef BOARD_N9 + if (ln_story_player_simple_start("/user/leiniao/story/choose")) + { + printf("播放开始成功\n"); + } + #endif + } + else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_STOP) + { + printf("LN_HTTP_SERVICE_CMD_AUDIO_STOP:停止播放音频\n"); + #ifdef BOARD_N9 + ln_story_player_simple_stop(); + #endif + } + else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT) + { + printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT:播放下一首\n"); + #ifdef BOARD_N9 + ln_story_player_simple_handle_message(LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT, NULL, 0); + #endif + } if (mail.data != NULL) { printf("free(mail.data)\n"); @@ -893,19 +924,19 @@ uint32_t ln_parse_and_process_json_data(const char *json_data, int interface_typ { case LN_HTTP_SERVICE_CMD_SSE_RECV: snprintf(save_dir, sizeof(save_dir), "%s/speech", LN_DATA_PATH); - snprintf(filename, sizeof(filename), "speech_audio_%d.mp3", segment_index); + snprintf(filename, sizeof(filename), "%d.mp3", segment_index); break; case LN_HTTP_RECV_STORY_CHOOSE: snprintf(save_dir, sizeof(save_dir), "%s/story/choose", LN_DATA_PATH); - snprintf(filename, sizeof(filename), "story_choose_%d.mp3", segment_index); + snprintf(filename, sizeof(filename), "%d.mp3", segment_index); break; case LN_HTTP_RECV_STORY_RANDOM: snprintf(save_dir, sizeof(save_dir), "%s/story/random", LN_DATA_PATH); - snprintf(filename, sizeof(filename), "story_random_%d.mp3", segment_index); + snprintf(filename, sizeof(filename), "%d.mp3", segment_index); break; default: snprintf(save_dir, sizeof(save_dir), "%s", LN_DATA_PATH); - snprintf(filename, sizeof(filename), "audio_%d.mp3", segment_index); + snprintf(filename, sizeof(filename), "%d.mp3", segment_index); break; } diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h index 5b927b0b2..982a3c33a 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h @@ -46,7 +46,7 @@ typedef struct /* OTA 包保存目录(最终文件仍将放在 /user/ 下)*/ #define LN_OTA_SAVE_DIR "/user" /* 用户数据保存目录 */ -#define LN_DATA_PATH "/user/leiniao/" +#define LN_DATA_PATH "/user/leiniao" #define LN_CLIENT_PREPARE_SIZE 2*1024 @@ -77,6 +77,11 @@ typedef struct #define LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD 0x51 /* 触发 OTA 包下载(根据 getTask 的返回 packageUrl)*/ #define LN_HTTP_RECV_OTA_DOWNLOAD_MSG 0x61 /* 可选:OTA 下载控制消息(JSON)接收)*/ +/* 音频播放相关命令 */ +#define LN_HTTP_SERVICE_CMD_AUDIO_PLAY 0x1001 /* 播放音频 */ +#define LN_HTTP_SERVICE_CMD_AUDIO_STOP 0x1002 /* 停止播放音频 */ +#define LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT 0x1003 /* 播放下一首 */ + typedef struct { char device_id[64]; -- 2.17.1