概述
music任务运行相关介绍。
main函数中进行必要初始化,创建任务。
int main()
{
#if(CONFIG_CPU_BR25)
#if (TCFG_DEC2TWS_ENABLE ||RECORDER_MIX_EN || TCFG_DRC_ENABLE || TCFG_USER_BLE_ENABLE || TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE || TCFG_USER_EMITTER_ENABLE)
clock_set_sfc_max_freq(100 * 1000000, 100 * 1000000);
#else
#if ((TCFG_AEC_ENABLE) && (TCFG_USER_TWS_ENABLE))
clock_set_sfc_max_freq(80 * 1000000, 80 * 1000000);
#else
clock_set_sfc_max_freq(64 * 1000000, 64 * 1000000);
#endif
#endif
#endif
wdt_close();//关闭看门狗
os_init();//操作系统初始化
setup_arch();//硬件初始化
board_early_init();//板级初始化
task_create(app_task_handler, NULL, "app_core");//创建任务
os_start();//启动操作系统
local_irq_enable();//本地中断使能
while (1) {
asm("idle");
}
return 0;
}
static void app_task_handler(void *p)//app任务
{
app_init();//app初始化
app_main();//运行app main
}
app_main中调用:app_task_loop();//运行app任务
app_task_loop中,根据app_curr_task变量,决定执行哪个任务。
case APP_MUSIC_TASK://music任务
log_info("APP_MUSIC_TASK n");
app_music_task();
break;
music任务:进行任务初始化、播放提示音、监控消息
void app_music_task()//music 主任务
{
int res;
int msg[32];//用于存储消息
music_task_start();//music任务初始化
#if (MUSIC_DEVICE_TONE_EN)//设备提示音使能
music_player_play_start();//music播放器播放提示音
#else
#if TCFG_DEC2TWS_ENABLE
extern void set_tws_background_connected_flag(u8 flag);
extern u8 get_tws_background_connected_flag();
if (get_tws_background_connected_flag()) { //不播放提示音
music_player_play_start();
set_tws_background_connected_flag(0);
} else
#endif
{
//第一个参数路径
//第二个参数打断标志
//第三个参数回调函数
//第四个参数事件回调私有句柄
tone_play_with_callback_by_name(tone_table[IDEX_TONE_MUSIC], 1, music_tone_play_end_callback, (void *)IDEX_TONE_MUSIC);
}
#endif
while (1) {
//msg用于存储消息
//ARRAY_SIZE(msg)表示存储消息的容量
//1表示获取后直接返回,不挂起等待
app_task_get_msg(msg, ARRAY_SIZE(msg), 1);//获取消息
switch (msg[0]) {
case APP_MSG_SYS_EVENT://系统事件
if (music_sys_event_handler((struct sys_event *)(&msg[1])) == false) {//如果music系统事件处理返回false
app_default_event_deal((struct sys_event *)(&msg[1]));//则进行系统默认事件处理
}
break;
default:
break;
}
if (app_task_exitting()) {//如果要退出
music_task_close();//播放器退出
return;
}
}
}
msg用于存储消息。
msg[0]字节:
enum {
APP_MSG_SYS_EVENT = Q_EVENT,//系统事件
/* 用户自定义消息 */
APP_MSG_SWITCH_TASK = Q_USER + 1,
APP_MSG_USER = Q_USER + 2,
};
msg[1]:事件类型,用于各个子任务模块自行处理的消息类型。
music的初始化。
UI界面的更新,是否显示歌词,显示则初始化歌词。
时钟初始化、按键事件使能。
创建播放器、创建断点。
static void music_task_start()
{
printf("music task start!!!!!n");
music_idle_flag = 0;
ui_update_status(STATUS_MUSIC_MODE);//ui更新
#if (TCFG_LRC_LYRICS_ENABLE)//歌词显示
extern int lrc_init(void);
lrc_init();//歌词初始化
#endif
///显示初始化
UI_SHOW_WINDOW(ID_WINDOW_MUSIC);
UI_SHOW_MENU(MENU_WAIT, 0, 0, NULL);
///时钟初始化
clock_idle(MUSIC_IDLE_CLOCK);
///按键使能
sys_key_event_enable();
///播放器初始化
struct __player_parm parm = {0};
parm.cb = &music_player_callback;//回调函数控制块
parm.scan_cb = &scan_cb;//扫描控制块
music_player_creat(NULL, &parm);//创建播放器
///获取断点句柄, 后面所有断点读/写都需要用到
breakpoint = breakpoint_handle_creat();//创建断点
///初始化一些参数
__this->file_err_counter = 0;//文件错误计数器清零
__this->file_play_direct = 0;//0:下一曲, 1:上一曲
__this->scandisk_break = 0;//扫描文件打断标志
memset(__this->device_tone_dev, 0, sizeof(__this->device_tone_dev));//提示音
}
播放器的创建。
bool music_player_creat(void *priv, struct __player_parm *parm)//music_player创建接口
{
__this = zalloc(sizeof(struct __music_player));//申请内存空间
if (__this == NULL) {
return false;
}
__this->priv = priv;
memcpy(&__this->parm, parm, sizeof(struct __player_parm));
ASSERT(__this->parm.cb, "music_player parm error!!n");
ASSERT(__this->parm.scan_cb, "music_player parm error 1 !!n");
return true;
}
struct __music_player结构体:
struct __music_player {
struct __dev *dev;//当前播放设备节点
struct vfscan *fsn;//设备扫盘句柄
FILE *file;//当前播放文件句柄
FILE *lrc_file;//当前播放歌词文件句柄
void *priv;//music回调函数,私有参数
struct __player_parm parm;//回调及参数配置等
};
static struct __music_player *music_player = NULL;//播放器句柄
#define __this music_player
播放器的创建主要是给__this申请内容空间、参数赋值。
断点的创建。
//创建一个bp
//申请空间,赋值长度
struct __breakpoint *breakpoint_handle_creat(void)//bp创建
{
struct __breakpoint *bp = (struct __breakpoint *)zalloc(sizeof(struct __breakpoint) + BREAKPOINT_DATA_LEN);
bp->dbp.data_len = BREAKPOINT_DATA_LEN;//不同音乐格式,长度不同
return bp;
}
断点信息结构体
struct __breakpoint {
u32 fsize; ///文件信息
u32 sclust;
struct audio_dec_breakpoint dbp;///解码信息
};
解码断点结构体
struct audio_dec_breakpoint {
int len;
u32 fptr;
int data_len;
u8 data[0];
// u8 data[128];
};
static struct __breakpoint *breakpoint = NULL;
断点指播放音乐文件时,暂停打断退出,需要记录当前播放位置的信息,下次进入播放时在该处继续播放。这里涉及到文件播放到哪了,需要录该文件当前的播放位置。文件在播放时进行了音频解码,这里也需要记录起来。
music 设备事件响应接口。
进行消息处理,如果是music可以处理的消息,则处理完后返回1。
如果不是music可以处理的消息,则返回0,系统将使用通用消息处理器进行该消息的处理。
//返回1表示事件已经处理
//返回0表示事件未处理,须有common公共事件处理函数来处理
处理了设备拔出事件
拔出的设备和当前播放设备必须是同一个设备
保存文件断点信息
static int music_sys_event_handler(struct sys_event *event)//music系统事件处理
{
int err = 0;
char *logo = NULL;
char *evt_logo = NULL;
switch (event->type) {//事件类型
case SYS_KEY_EVENT://按键事件
return music_key_event_opr(event);//调用music按键事件处理函数
case SYS_DEVICE_EVENT://设备事件
switch ((u32)event->arg) {
case DRIVER_EVENT_FROM_SD0:
case DRIVER_EVENT_FROM_SD1:
case DRIVER_EVENT_FROM_SD2:
evt_logo = (char *)event->u.dev.value;
case DEVICE_EVENT_FROM_OTG:
if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) {
evt_logo = (char *)"udisk0";
}
int str_len = 0;
logo = music_player_get_phy_dev(&str_len);//获取phy设备的logo
log_i("evt_logo =%s, logo = %s len =%dn", evt_logo, logo, str_len);
if (event->u.dev.event == DEVICE_EVENT_OUT) {//拔出
if (logo == NULL) {
break;
}
//当前播放设备logo和事件设备logo比较
if (logo && (0 == memcmp(logo, evt_logo, str_len))) {
///相同的设备才响应
if (music_player_get_playing_breakpoint(breakpoint, 1) == true) {//获取播放文件断点信息
breakpoint_vm_write(breakpoint, logo);//将断点信息和logo保存
}
memset(__this->device_tone_dev, 0, sizeof(__this->device_tone_dev));
///停止解码,防止设备掉线后还继续使用
music_player_stop(1);//停止解码,释放扫盘句柄
///重新选择活动设备播放
app_task_put_key_msg(KEY_MUSIC_PLAYER_START, 0);//卸载了设备再执行
log_i("KEY_MUSIC_PLAYER_START AFTER UMOUNTn");
}
} else {
#if (MUSIC_DEV_ONLINE_START_AFTER_MOUNT_EN == 0)//设备挂载后自动播放
music_task_dev_online_start();
#endif
}
break;
default://switch((u32)event->arg)
break;
}
break;//SYS_DEVICE_EVENT
default://switch (event->type)
break;
}
return false;//事件未处理
}
struct sys_event *event结构体如下:
struct sys_event {
u16 type;//类型
u8 consumed;//1表示接管按键消息,app应用不会收到消息
void *arg;//参数
union {
struct key_event key;//按键
struct axis_event axis;
struct codesw_event codesw;
#if EVENT_TOUCH_ENABLE_CONFIG
struct touch_event touch;//触摸屏
#endif
struct device_event dev;//设备
struct net_event net;//网路
struct bt_event bt;//蓝牙
struct msg_event msg;
struct chargestore_event chargestore;
struct soundbox_tool_event soundbox_tool;
struct ir_event ir;//红外
struct pbg_event pbg;
struct uart_event uart;
struct uart_cmd_event uart_cmd;
struct ai_event ai;
struct ear_event ear;
struct rcsp_event rcsp;
struct chargebox_event chargebox;
struct ancbox_event ancbox;
struct matrix_key_event matrix_key;
struct touchpad_event touchpad;
struct adt_event adt;
} u;
};
这里使用了联合体,将不同模块的消息都定义在联合体中。
type:
#define SYS_ALL_EVENT 0xffff
#define SYS_KEY_EVENT 0x0001//按键事件
#define SYS_TOUCH_EVENT 0x0002//触摸事件
#define SYS_DEVICE_EVENT 0x0004//设备事件
#define SYS_NET_EVENT 0x0008//网络事件
#define SYS_BT_EVENT 0x0010//蓝牙事件
#define SYS_IR_EVENT 0x0020//红外事件
#define SYS_PBG_EVENT 0x0040
#define SYS_BT_AI_EVENT 0x0080//蓝牙AI事件
#define SYS_AI_EVENT 0x0100//AI事件
#define SYS_MATRIX_KEY_EVENT 0x0200
#define SYS_TOUCHPAD_EVENT 0x0400//触摸板事件
#define SYS_ADT_EVENT 0x0800
最后
以上就是柔弱芝麻为你收集整理的music相关基础流程的全部内容,希望文章能够帮你解决music相关基础流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复