我是靠谱客的博主 柔弱芝麻,最近开发中收集的这篇文章主要介绍music相关基础流程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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相关基础流程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部