ESP-ADF esp_dispatcher组件之audio_service子模块详解
版本信息: v2.7-65-gcf908721
本章节分析的源码位于
/components/esp_dispatcher/audio_service.c
文件
子模块概览
基本功能与定位
audio_service子模块是ESP-ADF中的音频服务抽象层,它提供了统一的音频服务管理框架,使系统能够以一致的方式处理各种音频相关事件和状态。该模块位于ESP-ADF架构的中间层,连接上层应用逻辑和底层音频处理组件,依赖于delegate子模块提供的共享调度器机制。
这个图表展示了audio_service子模块在ESP-ADF架构中的位置以及与其他模块的关系。它是连接应用层和底层音频组件的桥梁,依赖delegate子模块提供的共享调度器机制,实现了对音频服务的统一管理。
工作原理
audio_service子模块基于回调机制和状态管理实现,其工作原理如下:
- 服务创建:应用程序通过API创建特定类型的音频服务实例
- 回调注册:注册事件回调函数,用于接收音频事件通知
- 服务连接:连接到音频服务,如蓝牙音频、网络音频流等
- 服务启动:启动服务,开始处理音频事件
- 事件处理:音频事件发生时,服务通过回调函数通知应用程序
- 服务停止:停止服务,不再处理音频事件
- 服务断开:断开与音频服务的连接
- 服务销毁:释放服务占用的资源
核心特性
- 统一服务接口:提供统一的服务创建、连接、启动、停止和销毁接口
- 事件回调机制:通过回调函数通知应用程序音频事件
- 状态管理:维护服务的状态(空闲、连接中、已连接、运行、停止等)
- 连接控制:提供连接和断开音频服务的专用接口
- 资源管理:自动管理任务、互斥锁等资源的创建和销毁
- 可扩展性:易于添加新的音频服务类型
audio_service与periph_service的对比
audio_service子模块与periph_service子模块在设计上有许多相似之处,但针对音频服务的特殊需求进行了扩展。下表对比了两者的主要区别:
特性 | audio_service | periph_service |
---|---|---|
状态类型 | 包含SERVICE_STATE_CONNECTING和SERVICE_STATE_CONNECTED等连接相关状态 | 只有基本的IDLE、RUNNING、STOPPED状态 |
专用接口 | 提供connect和disconnect专用接口 | 无连接专用接口 |
应用场景 | 音频流处理、编解码、播放控制等 | 按键、LED、触摸屏等外设控制 |
事件类型 | 音频特定事件(播放、暂停、音量等) | 外设特定事件(按下、释放等) |
这种设计使得audio_service特别适合处理需要连接建立的音频服务,如蓝牙音频、网络音频流等,同时保持了与periph_service一致的基本框架,便于开发者理解和使用。
公开接口
以下接口定义来自
/components/esp_dispatcher/include/audio_service.h
数据类型与结构体
// 音频服务状态
typedef enum {
SERVICE_STATE_UNKNOWN, // 未知状态
SERVICE_STATE_IDLE, // 空闲状态
SERVICE_STATE_CONNECTING, // 连接中状态
SERVICE_STATE_CONNECTED, // 已连接状态
SERVICE_STATE_RUNNING, // 运行状态
SERVICE_STATE_STOPPED, // 停止状态
} service_state_t;
// 音频服务事件信息
typedef struct {
int type; // 事件类型
void *source; // 事件源
void *data; // 事件数据
int len; // 数据长度
} service_event_t;
// 音频服务句柄
typedef struct audio_service_impl *audio_service_handle_t;
// 服务控制函数类型
typedef esp_err_t (*service_ctrl)(audio_service_handle_t handle);
// 服务回调函数类型
typedef esp_err_t (*service_callback)(audio_service_handle_t handle, service_event_t *evt, void *ctx);
// 音频服务配置
typedef struct {
int task_stack; // >0 服务任务栈大小; =0 不创建任务
int task_prio; // 服务任务优先级(基于FreeRTOS优先级)
int task_core; // 服务任务运行的核心(0或1)
TaskFunction_t task_func; // 服务任务函数
service_ctrl service_start; // 启动函数
service_ctrl service_stop; // 停止函数
service_ctrl service_connect; // 连接函数
service_ctrl service_disconnect; // 断开连接函数
service_ctrl service_destroy; // 销毁函数
const char *service_name; // 音频服务名称
void *user_data; // 用户数据
} audio_service_config_t;
公开函数
audio_service_create
/**
* @brief 创建音频服务实例
*
* @param config 音频服务实例的配置
*
* @return
* - NULL,失败
* - 其他,成功
*/
audio_service_handle_t audio_service_create(audio_service_config_t *config);
audio_service_destroy
/**
* @brief 销毁音频服务实例
*
* @param handle 音频服务实例
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_destroy(audio_service_handle_t handle);
audio_service_start
/**
* @brief 启动特定的音频服务
*
* @param handle 音频服务实例
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_start(audio_service_handle_t handle);
audio_service_stop
/**
* @brief 停止特定的音频服务
*
* @param handle 音频服务实例
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_stop(audio_service_handle_t handle);
audio_service_connect
/**
* @brief 连接特定的音频服务
*
* @param handle 音频服务实例
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_connect(audio_service_handle_t handle);
audio_service_disconnect
/**
* @brief 断开特定的音频服务
*
* @param handle 音频服务实例
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_disconnect(audio_service_handle_t handle);
audio_service_set_callback
/**
* @brief 设置特定音频服务的回调函数
*
* @param handle 音频服务实例
* @param cb 指向service_callback的指针
* @param ctx 指向用户上下文的指针
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_set_callback(audio_service_handle_t handle, service_callback cb, void *ctx);
audio_service_callback
/**
* @brief 通过配置调用音频服务
*
* @param handle 音频服务实例
* @param evt 指向service_event_t的指针
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_callback(audio_service_handle_t handle, service_event_t *evt);
audio_service_set_data
/**
* @brief 设置特定音频服务实例的用户数据
*
* @param handle 音频服务实例
* @param data 指向用户数据的指针
*
* @return
* - ESP_OK
* - ESP_FAIL
* - ESP_ERR_INVALID_ARG
*/
esp_err_t audio_service_set_data(audio_service_handle_t handle, void *data);
audio_service_get_data
/**
* @brief 获取特定音频服务实例的用户数据
*
* @param handle 音频服务实例
*
* @return 指向用户数据的指针
*/
void *audio_service_get_data(audio_service_handle_t handle);
内部实现
内部数据结构
audio_service子模块内部定义了关键的结构体,用于实现音频服务管理:
/**
* @brief 音频服务实现结构体
*/
typedef struct audio_service_impl {
service_ctrl service_start; // 服务启动函数
service_ctrl service_stop; // 服务停止函数
service_ctrl service_connect; // 服务连接函数
service_ctrl service_disconnect; // 服务断开连接函数
service_ctrl service_destroy; // 服务销毁函数
service_callback callback_func; // 回调函数
void *user_cb_ctx; // 用户回调上下文
char *service_name; // 服务名称
TaskHandle_t task_handle; // 任务句柄
void *user_data; // 用户数据
} audio_service_impl_t;
这个内部结构体保存了音频服务实例的所有状态和回调函数,包括启动、停止、连接、断开连接、销毁等控制函数,以及回调函数和用户数据。
结构体关系图
下面的图表展示了这些结构体之间的关系:
这个图表展示了音频服务的核心数据结构及其关系:
audio_service_config_t
是创建音频服务时的配置结构体,包含任务参数和各种回调函数audio_service_impl_t
是音频服务的内部实现结构体,由配置创建而来- 音频服务通过状态(
service_state_t
)和事件(service_event_t
)管理其生命周期和通知机制 - 各种回调函数类型(
service_ctrl
,service_callback
)定义了服务与应用程序的交互接口
接口总结
概述
ESP-ADF的audio_service子模块提供了一套完整的音频服务管理接口,主要用于创建和管理音频服务实例、处理音频事件、控制音频行为等。这些接口设计遵循了以下原则:
- 资源生命周期管理:通过create/destroy函数对服务资源进行完整生命周期管理
- 连接状态管理:通过connect/disconnect函数控制服务的连接状态
- 运行状态控制:通过start/stop函数控制服务的运行状态
- 事件回调机制:通过callback函数将音频事件通知给应用程序
- 数据共享机制:通过set_data/get_data函数在服务和应用程序之间共享数据
函数分类
根据功能,audio_service子模块的公开函数可以分为以下几类:
1. 资源管理函数
函数名 | 功能描述 |
---|---|
audio_service_create | 创建服务实例,分配必要资源 |
audio_service_destroy | 销毁服务实例,释放所有资源 |
2. 连接管理函数
函数名 | 功能描述 |
---|---|
audio_service_connect | 连接到音频服务 |
audio_service_disconnect | 断开与音频服务的连接 |
3. 状态控制函数
函数名 | 功能描述 |
---|---|
audio_service_start | 启动服务,开始处理音频事件 |
audio_service_stop | 停止服务,不再处理音频事件 |
4. 回调管理函数
函数名 | 功能描述 |
---|---|
audio_service_set_callback | 设置事件回调函数 |
audio_service_callback | 触发事件回调 |
5. 数据管理函数
函数名 | 功能描述 |
---|---|
audio_service_set_data | 设置服务实例的用户数据 |
audio_service_get_data | 获取服务实例的用户数据 |
通过这种设计,audio_service子模块为各种音频服务提供了统一的管理框架,简化了音频服务的开发和使用,使应用程序能够以一致的方式处理不同类型的音频服务。