本文所有代码均删除了次要代码,便于理解脉络
在app_init中的起点
int app_init(void)
{
app_audio_open();
app_audio_manager_open();
}
app_audio_handle_process的调用
app_audio_open注册le 音频处理函数, 这是app_thread所处理的mod_handler, 具体参考BES2300YP - 千头万绪的各种入口: 线程,中断,定时器 中的第二节
void app_audio_open(void)
{
app_audio_list_create();
app_set_threadhandle(APP_MODUAL_AUDIO, app_audio_handle_process);
}
app_thread每次收到一条mod_id为APP_MODUAL_AUDIO的消息时, 就会调用app_audio_handle_process
而发送APP_MODUAL_AUDIO消息是通过函数app_audio_sendrequest_param进行的
#define APP_AUDIO_SET_MESSAGE(appevt, id, status) (appevt = (((uint32_t)id&0xffff)<<16)|(status&0xffff))
// id : 流类型
// status: 流状态 = 操作类型
// ptr : sample rate
// param : 要求的系统主频
int app_audio_sendrequest_param(uint16_t id, uint8_t status, uint32_t ptr, uint32_t param)
{
// 把id和status组装成audevt
uint32_t audevt;
APP_AUDIO_SET_MESSAGE(audevt, id, status);
// 发送消息
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_AUDIO;
msg.msg_body.message_id = audevt;
msg.msg_body.message_ptr = ptr;
msg.msg_body.message_Param0 = param;
app_mailbox_put(&msg);
}
流类型
其中id的参数表示流类型,其取值有这些:
// \services\bt_app\app_bt_stream.h
// 这里有两类流, 一类是output stream,一类是input streams,
// 每类流同时只可以运行一种, 这一点在app_bt_stream_open中可以看到相关逻辑
#define APP_BT_STREAM_INVALID 0
// output streams
#define APP_BT_STREAM_HFP_PCM (1 << 0)
#define APP_BT_STREAM_HFP_CVSD (1 << 1)
#define APP_BT_STREAM_HFP_VENDOR (1 << 2)
#define APP_BT_STREAM_A2DP_SBC (1 << 3)
#define APP_BT_STREAM_A2DP_AAC (1 << 4)
#define APP_BT_STREAM_A2DP_VENDOR (1 << 5)
#define APP_FACTORYMODE_AUDIO_LOOP (1 << 6)
#define APP_PLAY_BACK_AUDIO (1 << 7)
#define APP_BT_STREAM_RBCODEC (1 << 8)
#define APP_PLAY_LINEIN_AUDIO (1 << 9)
#define APP_A2DP_SOURCE_LINEIN_AUDIO (1 << 10)
#define APP_A2DP_SOURCE_I2S_AUDIO (1 << 11)
// input streams
#define APP_BT_STREAM_VOICEPATH (1 << APP_BT_STREAM_BORDER_BIT_OFFSET)
#define APP_BT_STREAM_AI_VOICE (1 << (APP_BT_STREAM_BORDER_BIT_OFFSET+1))
控制命令
而参数status对应了播放器上最简单的控制功能, 把他叫做控制命令、动作命令可能更合适, 其可能的取值如下:
enum APP_BT_SETTING_T {
APP_BT_SETTING_OPEN = 0,
APP_BT_SETTING_CLOSE,
APP_BT_SETTING_SETUP,
APP_BT_SETTING_RESTART,
APP_BT_SETTING_CLOSEALL,
APP_BT_SETTING_CLOSEMEDIA,
APP_BT_SETTING_NUM,
};
代码走读
app_audio_handle_process中主要就是根据参数status(动作命令)进行处理,
其中主要涉及app_bt_stream系的open/close/setup等函数
有部分app_audio_list的内容, 我们先忽略他, 等后面有精力了再写
typedef struct {
uint16_t id;
uint16_t status;
uint16_t aud_type;
uint16_t aud_id;
uint8_t freq;
}APP_AUDIO_STATUS;
static int app_audio_handle_process(APP_MESSAGE_BODY *msg_body)
{
// 解读相关参数
APP_AUDIO_STATUS aud_status;
APP_AUDIO_GET_ID(msg_body->message_id, aud_status.id);
APP_AUDIO_GET_STATUS(msg_body->message_id, aud_status.status);
APP_AUDIO_GET_AUD_ID(msg_body->message_ptr, aud_status.aud_id);
APP_AUDIO_GET_FREQ(msg_body->message_Param0, aud_status.freq);
// 状态控制
switch (aud_status.status) {
case APP_BT_SETTING_OPEN:
if (app_audio_list_append(&aud_status))
{
app_bt_stream_open(&aud_status);
}
break;
case APP_BT_SETTING_CLOSE:
app_audio_switch_flash_proc();
APP_AUDIO_STATUS next_status;
app_bt_stream_close(aud_status.id);
app_audio_switch_flash_proc();
if (aud_status.id == APP_PLAY_BACK_AUDIO)
{
if (app_audio_get_list_playback_num()==1)
{
bt_media_stop(BT_STREAM_MEDIA, BT_DEVICE_ID_1);
}
}
if (app_audio_list_rmv_callback(&aud_status, &next_status,APP_BT_SETTING_Q_POS_HEAD, false))
{
app_bt_stream_open(&next_status);
}
break;
case APP_BT_SETTING_SETUP:
app_bt_stream_setup(aud_status.id, msg_body->message_ptr);
break;
case APP_BT_SETTING_RESTART:
app_bt_stream_restart(&aud_status);
break;
case APP_BT_SETTING_CLOSEALL:
app_bt_stream_closeall();
app_audio_list_clear();
app_audio_switch_flash_proc();
break;
}
}
欢迎阅读更多 BES专栏文章