在ESP-ADF 的框架下, 软件编程将 要实现的功能 虚拟化, 串了一串, 成为了 一条 “管道”。
“管道” 在大while 下 串流不息~~ 而在这个过程中如果触发了某一件事(需要做成对应的处理,例如打印个消息),可以添加和配置event,
从而在大while 下面 对event 传上来的msg 进行解析获取具体什么事情发生了。。。
第一步: 配置event,然后 通过初始化 这个配置 ,从而获取到该event 的句柄 (这个句柄 后期用于设置监听者用)
audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg);
AUDIO_EVENT_IFACE_DEFAULT_CFG(); 的具体配置信息如下:
其实event 就是一个queue ,配置的一些queue的size ,超时时间,回调函数等等
#define DEFAULT_AUDIO_EVENT_IFACE_SIZE (5)
#define AUDIO_EVENT_IFACE_DEFAULT_CFG() { \
.internal_queue_size = DEFAULT_AUDIO_EVENT_IFACE_SIZE, \
.external_queue_size = DEFAULT_AUDIO_EVENT_IFACE_SIZE, \
.queue_set_size = DEFAULT_AUDIO_EVENT_IFACE_SIZE, \
.on_cmd = NULL, \
.context = NULL, \
.wait_time = portMAX_DELAY, \
.type = 0, \
}
第二步: 设置监听者, 监听者有多种情况,
有些是已经被包含在”管道“ 中角色,
如在”管道“ pipeline 包含内容: [Bluetooth]-->bt_stream_reader-->i2s_stream_writer-->[codec_chip] 中, 需要监听bt 状态触发的事件。
则需要使用 pipeline 的 设置监听函数
audio_pipeline_set_listener(pipeline, evt);
有些是没有包含在管道中的 ,如触摸按键 这样外设。则采用下面函数设置监听者。
audio_event_iface_set_listener(esp_periph_get_event_iface(), evt);
esp_periph_get_event_iface() 得到的是一个 也是一个event 的句柄 audio_event_iface_handle_t
这个函数简化就是 set(a, listener);
将 event a 添加到 the listener 里面, 后面 我们就可以从 listen 中监听到a event。 (这里的listen 和 listener 是不同的)
第三步:在 大while 下 开始解析 event 传回来的msg
audio_event_iface_msg_t msg;
esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);
先看看 msg 结构体包含哪些信息
/**
* Event message
*/
typedef struct {
int cmd; /*!< Command id */
void *data; /*!< Data pointer */
int data_len; /*!< Data length */
void *source; /*!< Source event */
int source_type; /*!< Source type (To know where it came from) */
bool need_free_data; /*!< Need to free data pointer after the event has been processed */
} audio_event_iface_msg_t;
例子:
if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *) bt_stream_reader
&& msg.cmd == AEL_MSG_CMD_REPORT_MUSIC_INFO)
cmd ====>这个的值其实就是event id,它的内容主要根据source_type 来定,source_type 决定是element 还是 stream 还是什么,
而对应的每个element(或者stream)都是有对应的event id,
如果是AUDIO_ELEMENT_TYPE_ELEMENT 则cmd 分为以下几类,
/**
* Audio element action command, process on dispatcher
*/
typedef enum {
AEL_MSG_CMD_NONE = 0,
AEL_MSG_CMD_ERROR = 1,
AEL_MSG_CMD_FINISH = 2,
AEL_MSG_CMD_STOP = 3,
AEL_MSG_CMD_PAUSE = 4,
AEL_MSG_CMD_RESUME = 5,
AEL_MSG_CMD_DESTROY = 6,
// AEL_MSG_CMD_CHANGE_STATE = 7,
AEL_MSG_CMD_REPORT_STATUS = 8,
AEL_MSG_CMD_REPORT_MUSIC_INFO = 9,
AEL_MSG_CMD_REPORT_CODEC_FMT = 10,
} audio_element_msg_cmd_t;
但是根据 source_type 的不同,如果是PERIPH_ID_BLUETOOTH ,则cmd 又可以是以下的id
例如:
if (msg.source_type == PERIPH_ID_BLUETOOTH
&& msg.source == (void *)bt_periph) {
if (msg.cmd == PERIPH_BLUETOOTH_DISCONNECTED || msg.cmd == PERIPH_BLUETOOTH_AUDIO_SUSPENDED)
这些分类 主要是蓝牙的事件:
/**
* brief Bluetooth peripheral event id
*/
typedef enum {
PERIPH_BLUETOOTH_UNKNOWN = 0, /*!< No event */
PERIPH_BLUETOOTH_CONNECTED, /*!< A bluetooth device was connected */
PERIPH_BLUETOOTH_DISCONNECTED, /*!< Last connection was disconnected */
PERIPH_BLUETOOTH_AUDIO_STARTED, /*!< The audio session has been started */
PERIPH_BLUETOOTH_AUDIO_SUSPENDED, /*!< The audio session has been suspended */
PERIPH_BLUETOOTH_AUDIO_STOPPED, /*!< The audio session has been stopped */
} periph_bluetooth_event_id_t;
data====> 主要是element 的状态
/**
* Audio element status report
*/
typedef enum {
AEL_STATUS_NONE = 0,
AEL_STATUS_ERROR_OPEN = 1,
AEL_STATUS_ERROR_INPUT = 2,
AEL_STATUS_ERROR_PROCESS = 3,
AEL_STATUS_ERROR_OUTPUT = 4,
AEL_STATUS_ERROR_CLOSE = 5,
AEL_STATUS_ERROR_TIMEOUT = 6,
AEL_STATUS_ERROR_UNKNOWN = 7,
AEL_STATUS_INPUT_DONE = 8,
AEL_STATUS_INPUT_BUFFERING = 9,
AEL_STATUS_OUTPUT_DONE = 10,
AEL_STATUS_OUTPUT_BUFFERING = 11,
AEL_STATUS_STATE_RUNNING = 12,
AEL_STATUS_STATE_PAUSED = 13,
AEL_STATUS_STATE_STOPPED = 14,
AEL_STATUS_MOUNTED = 15,
AEL_STATUS_UNMOUNTED = 16,
} audio_element_status_t;
source =====> 这一项其实就是 一开始在做”管道“ 注册时,各个组件的 句柄
如注册 时
audio_pipeline_register(pipeline, bt_stream_reader, "bt");
audio_pipeline_register(pipeline, i2s_stream_writer, "i2s");
那么bt_stream_reader和i2s_stream_writer 都将是source的 可选值之一。
source_type ====》就是触发事件的 element 的 id
首先分为5大类
typedef enum {
AUDIO_ELEMENT_TYPE_UNKNOW = 0x01<<ELEMENT_SUB_TYPE_OFFSET,
AUDIO_ELEMENT_TYPE_ELEMENT= 0x01<<(ELEMENT_SUB_TYPE_OFFSET+1),
AUDIO_ELEMENT_TYPE_PLAYER = 0x01<<(ELEMENT_SUB_TYPE_OFFSET+2),
AUDIO_ELEMENT_TYPE_SERVICE = 0x01<<(ELEMENT_SUB_TYPE_OFFSET+3),
AUDIO_ELEMENT_TYPE_PERIPH = 0x01<<(ELEMENT_SUB_TYPE_OFFSET+4),
} audio_element_type_t;
在这5大类中每一类都有衍生, 例如硬件外设,就具体分了下面几种。
/**
* @brief Peripheral Identify, this must be unique for each peripheral added to the peripherals list
*/
typedef enum {
PERIPH_ID_BUTTON = AUDIO_ELEMENT_TYPE_PERIPH + 1,
PERIPH_ID_TOUCH = AUDIO_ELEMENT_TYPE_PERIPH + 2,
PERIPH_ID_SDCARD = AUDIO_ELEMENT_TYPE_PERIPH + 3,
PERIPH_ID_WIFI = AUDIO_ELEMENT_TYPE_PERIPH + 4,
PERIPH_ID_FLASH = AUDIO_ELEMENT_TYPE_PERIPH + 5,
PERIPH_ID_AUXIN = AUDIO_ELEMENT_TYPE_PERIPH + 6,
PERIPH_ID_ADC = AUDIO_ELEMENT_TYPE_PERIPH + 7,
PERIPH_ID_CONSOLE = AUDIO_ELEMENT_TYPE_PERIPH + 8,
PERIPH_ID_BLUETOOTH = AUDIO_ELEMENT_TYPE_PERIPH + 9,
} esp_periph_id_t;
其余两个值暂时还没有例子可循, 说到这里发现自己还是没有深入的理解,感觉更多只是在贴代码~~~
希望有高手可以帮忙斧正!
最近编辑记录 mkseven32 (2018-05-16 10:08:48)
离线
感谢楼主分享!
离线
强烈建议楼主带小白入局:win10 64位,想用乐鑫的编译链,搭建adf屡次失败,现在用着idf cmake好好的。我的球球36351109.
离线