Files
arcs/arcs-sdk/components/app_player/app_player.h
2026-08-13 16:50:52 +08:00

436 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright (c) 2025, LISTENAI
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __LISTENAI_APP_PLAYER_H__
#define __LISTENAI_APP_PLAYER_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
// ==================== 前置声明 ====================
typedef struct app_player_s app_player_t;
/**
* @brief 播放器错误码
*/
typedef enum {
APP_PLAYER_OK = 0, /**< 成功 */
APP_PLAYER_ERR_INVALID_PARAM = -1, /**< 无效参数 */
APP_PLAYER_ERR_NO_MEMORY = -2, /**< 内存不足 */
APP_PLAYER_ERR_INVALID_STATE = -3, /**< 状态错误 */
APP_PLAYER_ERR_NOT_SUPPORTED = -4, /**< 不支持的操作 */
APP_PLAYER_ERR_TIMEOUT = -5, /**< 超时 */
APP_PLAYER_ERR_IO = -6, /**< IO 错误 */
} app_player_err_t;
/**
* @brief PA 控制回调函数类型
* @param onoff 1: 打开PA, 0: 关闭PA
* @return 0: 成功, 其他值: 失败
*/
typedef int (*app_player_pa_ctrl_cb_t)(int onoff);
// ==================== 音频焦点管理类型(可选功能) ====================
#ifdef CONFIG_APP_PLAYER_AUDIO_FOCUS
/**
* @brief 播放器焦点状态
*/
typedef enum {
APP_PLAYER_FOCUS_FOREGROUND = 0, /**< 前景焦点:正常播放 */
APP_PLAYER_FOCUS_BACKGROUND, /**< 背景焦点:降级播放(暂停或降音量) */
APP_PLAYER_FOCUS_NONE /**< 无焦点:停止播放 */
} app_player_focus_state_t;
/**
* @brief 焦点丢失策略
*/
typedef enum {
APP_PLAYER_FOCUS_LOSS_IGNORE = 0, /**< 忽略焦点变化,继续播放 */
APP_PLAYER_FOCUS_LOSS_PAUSE, /**< 暂停播放(可自动恢复) */
APP_PLAYER_FOCUS_LOSS_STOP, /**< 停止播放(不可自动恢复) */
APP_PLAYER_FOCUS_LOSS_DUCK, /**< 降低音量(暂不支持) */
} app_player_focus_loss_policy_t;
/**
* @brief 焦点行为配置
*/
typedef struct {
app_player_focus_loss_policy_t on_background; /**< 变为后景时的策略 */
app_player_focus_loss_policy_t on_focus_lost; /**< 完全失去焦点时的策略 */
uint8_t duck_volume_percent; /**< 降低音量时的百分比(0-100)(暂不支持) */
} app_player_focus_behavior_t;
/**
* @brief 焦点变化回调函数
* @param player 播放器实例
* @param new_state 新的焦点状态
* @param by_which 触发焦点变化的播放器句柄
* @param user_data 用户自定义数据
* @return true=完全接管处理app_player不执行任何操作false=执行默认策略
*
* @note 此回调在焦点状态变化时由焦点管理器调用,用于通知应用层焦点变化事件
* @note 返回值控制行为:
* - 返回 falseapp_player 根据 behavior 配置自动执行策略pause/stop/ignore
* - 返回 trueapp_player 完全跳过处理,由应用层自行处理
* @warning 回调函数应快速返回,避免阻塞焦点管理器
* 耗时操作应提交到任务队列异步执行
*/
typedef bool (*app_player_focus_change_cb_t)(app_player_t *player,
app_player_focus_state_t new_state,
app_player_t *by_which,
void *user_data);
/**
* @brief 焦点通道配置(静态属性)
*/
typedef struct {
const char *name; /**< 通道名称(需与 app_player_create 的 name 匹配) */
int priority; /**< 优先级数值越小优先级越高0 = 最高) */
const char **capture_names; /**< 可抢占的通道名称列表(通过 name 引用其他播放器) */
int capture_count; /**< 抢占列表长度 */
app_player_focus_behavior_t behavior; /**< 焦点丢失时的行为配置 */
} app_player_focus_channel_config_t;
#endif // CONFIG_APP_PLAYER_AUDIO_FOCUS
/**
* @brief app_player 初始化配置结构体
*/
typedef struct {
app_player_pa_ctrl_cb_t pa_ctrl_callback; /**< PA 控制回调函数(必填) */
#ifdef CONFIG_APP_PLAYER_AUDIO_FOCUS
const app_player_focus_channel_config_t *focus_configs; /**< 焦点通道配置数组(可选) */
int focus_config_count; /**< 焦点通道配置数量 */
#endif
} app_player_config_t;
/**
* @brief 播放器状态
*/
typedef enum {
APP_PLAYER_STATE_IDLE = 0, /**< 空闲状态 */
APP_PLAYER_STATE_PREPARING, /**< 准备中 */
APP_PLAYER_STATE_PREPARED, /**< 准备完成 */
APP_PLAYER_STATE_PLAYING, /**< 播放中 */
APP_PLAYER_STATE_PAUSED, /**< 已暂停 */
APP_PLAYER_STATE_STOPPED, /**< 已停止 */
APP_PLAYER_STATE_ERROR /**< 错误状态 */
} app_player_state_t;
/**
* @brief 播放器事件类型
*/
typedef enum {
APP_PLAYER_EVENT_ERROR = 0, /**< 播放错误 */
APP_PLAYER_EVENT_PREPARED, /**< 准备完成 */
APP_PLAYER_EVENT_PLAYING, /**< 播放中 */
APP_PLAYER_EVENT_PAUSED, /**< 已暂停 */
APP_PLAYER_EVENT_STOPPED, /**< 已停止 */
APP_PLAYER_EVENT_COMPLETED, /**< 播放完成 */
APP_PLAYER_EVENT_SEEK_COMPLETE, /**< Seek 完成 */
} app_player_event_t;
/**
* @brief 播放器事件回调函数
* @param player 播放器实例
* @param event 事件类型
* @param user_data 用户自定义数据
*/
typedef void (*app_player_event_cb_t)(app_player_t *player, app_player_event_t event, void *user_data);
/**
* @brief 高级播放选项
*/
typedef struct {
const char *url; /**< 播放 URL必填 */
uint32_t throw_time_ms; /**< 开始指定时长内的低能量段毫秒0=不跳过) */
} app_player_play_opt_t;
/**
* @brief 初始化 app_player 模块
* @param config 初始化配置参数
* @return APP_PLAYER_OK 成功,其他表示错误
* @note 必须在创建播放器实例前调用此函数
* @note config 中的 pa_ctrl_callback 不能为 NULL
*/
int app_player_init(const app_player_config_t *config);
/**
* @brief 创建播放器实例
* @param name 播放器名称
* @return 播放器实例指针,失败返回 NULL
*/
app_player_t *app_player_create(const char *name);
/**
* @brief 销毁播放器实例
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_destroy(app_player_t *player);
/**
* @brief 注册事件回调
* @param player 播放器实例
* @param event_cb 事件回调函数
* @param user_data 用户数据
* @return APP_PLAYER_OK 成功,其他表示错误
* @note 建议在首次播放前调用
*/
int app_player_register_callback(app_player_t *player, app_player_event_cb_t event_cb, void *user_data);
/**
* @brief 播放指定 URL
* @param player 播放器实例
* @param url 播放地址(支持 http://, https://等)
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_play(app_player_t *player, const char *url);
/**
* @brief 高级播放接口(支持更多选项)
* @param player 播放器实例
* @param opt 播放选项
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_play_ex(app_player_t *player, const app_player_play_opt_t *opt);
/**
* @brief 停止播放(异步)
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
* @warning 流式播放模式下不支持此操作
*/
int app_player_stop(app_player_t *player);
/**
* @brief 停止播放(同步,等待停止完成)
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
* @warning 流式播放模式下不支持此操作
*/
int app_player_stop_sync(app_player_t *player);
/**
* @brief 暂停播放
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
* @warning 流式播放模式下不支持此操作
*/
int app_player_pause(app_player_t *player);
/**
* @brief 恢复播放(异步)
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
* @warning 流式播放模式下不支持此操作
*/
int app_player_resume(app_player_t *player);
/**
* @brief 恢复播放(同步,等待恢复完成)
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
* @warning 流式播放模式下不支持此操作
*/
int app_player_resume_sync(app_player_t *player);
/**
* @brief 重置播放器到初始状态
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_reset(app_player_t *player);
/**
* @brief 跳转到指定位置
* @param player 播放器实例
* @param seek_ms 跳转位置(毫秒)
* @return APP_PLAYER_OK 成功,其他表示错误
* @warning 流式播放模式下不支持此操作
*/
int app_player_seek(app_player_t *player, uint32_t seek_ms);
/**
* @brief 获取播放器状态
* @param player 播放器实例
* @return 播放器状态
*/
app_player_state_t app_player_get_state(app_player_t *player);
/**
* @brief 获取当前播放位置
* @param player 播放器实例
* @param position 输出参数,当前位置(毫秒)
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_get_position(app_player_t *player, uint32_t *position);
/**
* @brief 获取总时长
* @param player 播放器实例
* @param duration 输出参数,总时长(毫秒)
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_get_duration(app_player_t *player, uint32_t *duration);
/**
* @brief 设置音量
* @param player 播放器实例
* @param volume 音量值1-100
* @return APP_PLAYER_OK 成功,其他表示错误
*/
int app_player_set_volume(app_player_t *player, uint8_t volume);
/**
* @brief 开始流式播放
* @param player 播放器实例
* @param sample_rate 采样率Hz如 8000, 16000, 48000
* @param channels 声道数(当前仅支持 1
* @param bits 位深度(当前仅支持 16
* @return APP_PLAYER_OK 成功,其他表示错误
* @note 调用此函数后,使用 app_player_write_stream 写入 PCM 数据
* @note 流式播放适用于实时音频合成、网络音频流等场景
* @warning 流式播放模式仅支持以下操作流程:
* app_player_play_stream -> app_player_write_stream -> app_player_finish_stream
* 流式播放模式下不支持 seek/pause/stop/resume 等操作
*/
int app_player_play_stream(app_player_t *player, uint32_t sample_rate, uint8_t channels, uint8_t bits);
/**
* @brief 写入流数据
* @param player 播放器实例
* @param data 数据指针
* @param size 数据大小(字节)
* @param timeout_ms 超时时间(毫秒)
* @return 实际写入的字节数,<0 表示错误
* @note 必须先调用 app_player_play_stream 开启流式播放
* @note 支持多次调用以逐块写入数据
* @warning 仅在流式播放模式下有效,必须先调用 app_player_play_stream
*/
int app_player_write_stream(app_player_t *player, const uint8_t *data, uint32_t size, uint32_t timeout_ms);
/**
* @brief 结束流式播放
* @param player 播放器实例
* @return APP_PLAYER_OK 成功,其他表示错误
* @note 通知播放器所有流数据已写入完毕,等待播放完成
* @note 调用此函数后将收到 APP_PLAYER_EVENT_COMPLETED 事件
* @warning 仅在流式播放模式下有效,调用后退出流式播放模式
*/
int app_player_finish_stream(app_player_t *player);
// ==================== 音频焦点管理 API可选功能 ====================
#ifdef CONFIG_APP_PLAYER_AUDIO_FOCUS
/**
* @brief 注册播放器焦点变化回调
* @param player 播放器实例
* @param on_focus_change 焦点状态变化回调函数(可为 NULL 仅使用默认策略)
* @param user_data 用户自定义数据(传递给回调)
* @return APP_PLAYER_OK 成功,其他表示错误
*
* @note 需要在 app_player_init() 时配置过焦点通道focus_configs
* @note 如果未配置焦点通道,该播放器将不参与焦点管理
* @note 可以在播放器创建后的任意时刻调用,甚至可以动态更换回调
* @note 焦点变化时app_player 会根据 behavior 配置自动执行策略,
* 除非回调返回 true 表示完全接管
*
* @par 示例1仅监听焦点变化使用默认策略
* @code
* bool music_focus_cb(app_player_t *player, app_player_focus_state_t state,
* app_player_t *by_which, void *user_data) {
* LOGI("Focus changed to %d by player %p", state, by_which);
* return false; // 让 app_player 执行配置的策略
* }
*
* app_player_register_focus_cb(music, music_focus_cb, NULL);
* @endcode
*
* @par 示例2完全自定义焦点处理
* @code
* bool music_focus_cb(app_player_t *player, app_player_focus_state_t state,
* app_player_t *by_which, void *user_data) {
* if (state == APP_PLAYER_FOCUS_BACKGROUND) {
* // 自定义:降低音量而不是暂停
* app_player_set_volume(player, 30);
* return true; // 阻止 app_player 执行默认策略
* }
* return false; // 其他情况使用默认策略
* }
* @endcode
*/
int app_player_register_focus_cb(app_player_t *player,
app_player_focus_change_cb_t on_focus_change,
void *user_data);
/**
* @brief 设置播放器的焦点行为策略(运行时动态修改)
* @param player 播放器实例
* @param behavior 新的焦点行为配置
* @return APP_PLAYER_OK 成功,其他表示错误
*
* @note 此函数允许在运行时动态修改播放器的焦点行为策略
* @note 仅对已注册焦点通道的播放器有效
* @note 不会影响其他播放器的配置
* @note 修改后的配置立即生效,影响后续的焦点变化处理
* @warning 建议在播放器空闲状态下调用,避免影响正在进行的焦点处理
*
* @par 使用示例:
* @code
* // 修改 MUSIC 播放器的焦点行为
* app_player_focus_behavior_t new_behavior = {
* .on_background = APP_PLAYER_FOCUS_LOSS_IGNORE, // 后景继续播放
* .on_focus_lost = APP_PLAYER_FOCUS_LOSS_STOP, // 完全失焦停止
* };
* app_player_set_focus_behavior(g_music_player, &new_behavior);
* @endcode
*/
int app_player_set_focus_behavior(app_player_t *player,
const app_player_focus_behavior_t *behavior);
/**
* @brief 获取播放器当前的焦点行为策略
* @param player 播放器实例
* @param behavior 输出参数,当前的焦点行为配置
* @return APP_PLAYER_OK 成功,其他表示错误
*
* @note 可用于保存和恢复焦点行为配置
*
* @par 使用示例:
* @code
* // 保存原始配置
* app_player_focus_behavior_t original_behavior;
* app_player_get_focus_behavior(g_music_player, &original_behavior);
*
* // 修改配置进行测试
* app_player_focus_behavior_t test_behavior = { ... };
* app_player_set_focus_behavior(g_music_player, &test_behavior);
*
* // 恢复原始配置
* app_player_set_focus_behavior(g_music_player, &original_behavior);
* @endcode
*/
int app_player_get_focus_behavior(app_player_t *player,
app_player_focus_behavior_t *behavior);
#endif // CONFIG_APP_PLAYER_AUDIO_FOCUS
#ifdef __cplusplus
}
#endif
#endif // __LISTENAI_APP_PLAYER_H__