#ifdef SUPPORT_MS_EXTENSIONS #pragma bss_seg(".music_player.data.bss") #pragma data_seg(".music_player.data") #pragma const_seg(".music_player.text.const") #pragma code_seg(".music_player.text") #endif #include "music/music_player.h" #include "key_event_deal.h" #include "app_config.h" #include "app_main.h" #include "vm.h" #include "dev_manager.h" #include "file_player.h" #define LOG_TAG_CONST APP_MUSIC #define LOG_TAG "[APP_MUSIC]" #define LOG_ERROR_ENABLE #define LOG_DEBUG_ENABLE #define LOG_INFO_ENABLE /* #define LOG_DUMP_ENABLE */ #define LOG_CLI_ENABLE #include "debug.h" //播放参数,文件扫描时用,文件后缀等 static const char scan_parm[] = "-t" #if (TCFG_DEC_MP3_ENABLE) "MP1MP2MP3" #endif #if (TCFG_DEC_WMA_ENABLE) "WMA" #endif #if ( TCFG_DEC_WAV_ENABLE) "WAV" #endif #if (TCFG_DEC_DTS_ENABLE) "DTS" #endif #if (TCFG_DEC_FLAC_ENABLE) "FLA" #endif #if (TCFG_DEC_APE_ENABLE) "APE" #endif #if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_AAC_ENABLE) "M4AAAC" #endif #if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE) "M4AMP4" #endif #if (TCFG_DEC_AMR_ENABLE) "AMR" #endif #if (TCFG_DEC_OGG_VORBIS_ENABLE) "OGG" #endif #if (TCFG_DEC_OGG_OPUS_ENABLE) "OGGOPUS" #endif #if (TCFG_DEC_DECRYPT_ENABLE) "SMP" #endif #if (TCFG_DEC_MIDI_ENABLE) "MID" #endif #if (TCFG_DEC_AIFF_ENABLE) "AIFAIFFAIFC" #endif " -sn -r" #if (TCFG_RECORD_FOLDER_DEV_ENABLE) " -m" REC_FOLDER_NAME #endif ; extern u8 bt_emitter_pp(u8 pp); static volatile u8 save_mode_cnt = 0; static volatile u16 save_mode_timer = 0; /*----------------------------------------------------------------------------*/ /**@brief music_player循环模式处理接口 @param @return @note */ /*----------------------------------------------------------------------------*/ static void music_player_mode_save_do(void *priv) { local_irq_disable(); if (++save_mode_cnt >= 5) { if (save_mode_timer) { sys_timer_del(save_mode_timer); } save_mode_timer = 0; save_mode_cnt = 0; local_irq_enable(); syscfg_write(CFG_MUSIC_MODE, &app_var.cycle_mode, 1); return; } local_irq_enable(); } /*----------------------------------------------------------------------------*/ /**@brief music_player初始化 @param @return @note */ /*----------------------------------------------------------------------------*/ struct music_player *music_player_creat(void) { struct music_player *player_hd = zalloc(sizeof(struct music_player)); ASSERT(player_hd); return player_hd; } /*----------------------------------------------------------------------------*/ /**@brief music_playe注册扫盘回调 @param @return @note */ /*----------------------------------------------------------------------------*/ bool music_player_reg_scandisk_callback(struct music_player *player_hd, const struct __scan_callback *scan_cb) { if (player_hd) { player_hd->parm.scan_cb = scan_cb; return true; } return false; } /*----------------------------------------------------------------------------*/ /**@brief music_playe注册解码状态回调 @param @return @note */ /*----------------------------------------------------------------------------*/ bool music_player_reg_dec_callback(struct music_player *player_hd, const struct __player_cb *cb) { if (player_hd) { player_hd->parm.cb = cb; return true; } return false; } /*----------------------------------------------------------------------------*/ /**@brief music_player释放接口 @param @return @note */ /*----------------------------------------------------------------------------*/ void music_player_destroy(struct music_player *player_hd) { if (player_hd) { music_player_stop(player_hd, 1); free(player_hd); /* player_hd = NULL; */ } } /*----------------------------------------------------------------------------*/ /**@brief music_player播放结束处理 @param parm:结束参数 @return @note */ /*----------------------------------------------------------------------------*/ int music_player_end_deal(struct music_player *player_hd, int parm) { int err = 0; u8 read_err = (u8)(parm); //文件播放结束, 包括正常播放结束和读文件错误导致的结束, 如拔掉设备产生的错误结束 log_i("STREAM_EVENT_STOP\n"); if (read_err) { log_e("read err %d\n", read_err); if (read_err == 1) { err = MUSIC_PLAYER_ERR_FILE_READ;//文件读错误 } else { err = MUSIC_PLAYER_ERR_DEV_READ;//设备读错误 } } else { //正常结束,自动下一曲 #if (MUSIC_PLAYER_CYCLE_ALL_DEV_EN) if (player_hd->fsn == NULL) { log_e("player_hd->fsn is NULL\n"); return MUSIC_PLAYER_ERR_INVALID_STATE; } u32 cur_file = player_hd->fsn->file_counter; if ((music_player_get_record_play_status(player_hd) == false) && (app_var.cycle_mode == FCYCLE_ALL) && (cur_file >= player_hd->fsn->file_number) && (dev_manager_get_total(1) > 1)) { char *logo = music_player_get_dev_flit(player_hd, "_rec", 1); if (logo) { err = music_player_play_first_file(player_hd, logo); return err; } } #endif err = music_player_play_auto_next(player_hd); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player解码错误处理 @param event:err事件 @return @note */ /*----------------------------------------------------------------------------*/ int music_player_decode_err_deal(struct music_player *player_hd, int event) { int err = 0; switch (event) { case STREAM_EVENT_NONE: //解码启动错误, 这里将错误码转换为music_player错误类型 err = MUSIC_PLAYER_ERR_DECODE_FAIL; break; default: break; } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player播放结束事件回调 @param @return @note 非api层接口 */ /*----------------------------------------------------------------------------*/ static int music_player_decode_event_callback(void *priv, int parm, enum stream_event event) { struct music_player *player_hd = (struct music_player *)priv; if (player_hd == NULL) { log_e("player_hd is NULL\n"); return -1; } if (event == STREAM_EVENT_STOP) { if (player_hd->parm.cb && player_hd->parm.cb->end) { player_hd->parm.cb->end(player_hd->priv, parm); } } else if (event == STREAM_EVENT_START) { if (player_hd->parm.cb && player_hd->parm.cb->start) { player_hd->parm.cb->start(player_hd->priv, 0); } } else if (event == STREAM_EVENT_NONE) { if (player_hd->parm.cb && player_hd->parm.cb->err) { player_hd->parm.cb->err(player_hd->priv, STREAM_EVENT_NONE); } } return 0; } /*----------------------------------------------------------------------------*/ /**@brief music_player解码器启动接口 @param file: 文件句柄 dbp: 断点信息 @return music_player 错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_decode_start(struct music_player *player_hd, FILE *file, struct audio_dec_breakpoint *dbp) { if (file) { //get file short name u8 file_name[12 + 1] = {0}; //8.3+\0 fget_name(file, file_name, sizeof(file_name)); log_i("\n"); log_i("file name: %s\n", file_name); log_i("\n"); } struct file_player *file_player; if (!dbp) { dbp = music_app_get_dbp_addr(); if (dbp) { dbp->len = 0; } } file_player = music_file_play_callback(file, (void *)player_hd, music_player_decode_event_callback, dbp); if (!file_player) { return MUSIC_PLAYER_ERR_DECODE_FAIL; } #if TCFG_USER_EMITTER_ENABLE if (bt_emitter_get_curr_channel_state()) { bt_emitter_pp(1); } #endif return MUSIC_PLAYER_SUCC; } /*----------------------------------------------------------------------------*/ /**@brief music_player获取当前播放设备断点信息 @param bp: 断点缓存,外部调用提供 flag: 1:需要获取歌曲断点信息及文件信息, 0:只获取文件信息 @return 成功与否 @note */ /*----------------------------------------------------------------------------*/ bool music_player_get_playing_breakpoint(struct music_player *player_hd, struct __breakpoint *bp, u8 flag) { if (player_hd == NULL || bp == NULL) { return false; } int data_len = bp->dbp.data_len; struct __breakpoint *temp_bp = zalloc(sizeof(struct __breakpoint) + data_len); temp_bp->dbp.data_len = data_len; if (dev_manager_online_check(player_hd->dev, 1)) { if (music_player_runing()) { if (player_hd->file) { if (flag) { //获取断点解码信息 struct file_player *file_player = get_music_file_player(); int ret = music_file_get_breakpoints(&temp_bp->dbp, file_player); if (ret) { //获取断点解码信息错误 log_e("file_dec_get_breakpoint err !!\n"); } } memcpy(bp->dbp.data, temp_bp->dbp.data, temp_bp->dbp.len); bp->dbp.len = temp_bp->dbp.len; //获取断点文件信息 struct vfs_attr attr = {0}; fget_attrs(player_hd->file, &attr); bp->sclust = attr.sclust; bp->fsize = attr.fsize; log_i("get playing breakpoint ok\n"); free(temp_bp); mem_stats(); return true; } } else { //设备在线,但是音乐播放流已经结束了,断点已经由解码节点保存过了 free(temp_bp); return true; } } free(temp_bp); return false; } /*----------------------------------------------------------------------------*/ /**@brief music_player获取文件句柄 @param @return 文件句柄 @note 需要注意文件句柄的生命周期 */ /*----------------------------------------------------------------------------*/ FILE *music_player_get_file_hdl(struct music_player *player_hd) { if (player_hd && player_hd->file) { return player_hd->file; } return NULL; } void music_player_remove_file_hdl(struct music_player *player_hd) { if (player_hd && player_hd->file) { player_hd->file = NULL; } } /*----------------------------------------------------------------------------*/ /**@brief music_player获取当前播放设备下一个设备 @param @return 设备盘符 @note */ /*----------------------------------------------------------------------------*/ char *music_player_get_dev_next(struct music_player *player_hd, u8 auto_next) { if (player_hd) { if (auto_next) { return dev_manager_get_logo(dev_manager_find_next(player_hd->dev, 1)); } else { //跳过录音设备 struct __dev *next = dev_manager_find_next(player_hd->dev, 1); if (next) { char *logo = dev_manager_get_logo(next); if (logo) { char *str = strstr(logo, "_rec"); if (str) { char *cur_phy_logo = dev_manager_get_phy_logo(player_hd->dev); char *next_phy_logo = dev_manager_get_phy_logo(next); if (cur_phy_logo && next_phy_logo && strcmp(cur_phy_logo, next_phy_logo) == 0) { //是同一个物理设备的录音设别, 跳过 next = dev_manager_find_next(next, 1); if (next != player_hd->dev) { logo = dev_manager_get_logo(next); return logo; } else { //没有其他设备了(只有录音文件夹设备及本身) return NULL; } } } return logo; } } } } return NULL; } /*----------------------------------------------------------------------------*/ /**@brief music_player获取当前播放设备上一个设备 @param @return 设备盘符 @note */ /*----------------------------------------------------------------------------*/ char *music_player_get_dev_prev(struct music_player *player_hd) { if (player_hd) { return dev_manager_get_logo(dev_manager_find_prev(player_hd->dev, 1)); } return NULL; } //*----------------------------------------------------------------------------*/ /**@brief music_player获取当前播放状态 @param @return 返回值如:enum play_status @note */ /*----------------------------------------------------------------------------*/ int music_player_get_play_status(void) { struct file_player *file_player = get_music_file_player(); if (!file_player) { return FILE_PLAYER_STOP; } return music_file_get_player_status(file_player); } /*----------------------------------------------------------------------------*/ /**@brief music_player获取当前播放循环模式 @param @return 当前播放循环模式 @note */ /*----------------------------------------------------------------------------*/ u8 music_player_get_repeat_mode(void) { return app_var.cycle_mode; } /*----------------------------------------------------------------------------*/ /**@brief music_player获取当前播放对应的music设备 @param @return 设备盘符 @note 播放录音区分时,可以通过该接口判断当前播放的音乐设备是什么以便做录音区分判断 */ /*----------------------------------------------------------------------------*/ char *music_player_get_cur_music_dev(struct music_player *player_hd) { if (player_hd) { char *logo = dev_manager_get_logo(player_hd->dev); if (logo) { char *str = strstr(logo, "_rec"); if (str) { int log_len = strlen(logo) - strlen(str); char *music_dev_logo = malloc(log_len + 1); ASSERT(music_dev_logo); //录音设备,切换到音乐设备播放 strncpy(music_dev_logo, logo, log_len); music_dev_logo[log_len] = '\0'; logo = dev_manager_get_logo(dev_manager_find_spec(music_dev_logo, 1)); free(music_dev_logo); } } return logo; } return NULL; } const char *music_player_get_phy_dev(struct music_player *player_hd, int *len) { if (player_hd) { char *logo = dev_manager_get_logo(player_hd->dev); if (logo) { char *str = strstr(logo, "_rec"); if (str) { //录音设备,切换到音乐设备播放 if (len) { *len = strlen(logo) - strlen(str); } } else { if (len) { *len = strlen(logo); } } return logo; } } if (len) { *len = 0; } return NULL; } /*----------------------------------------------------------------------------*/ /**@brief music_player获取当前录音区分播放状态 @param @return true:录音文件夹播放, false:非录音文件夹播放 @note 播放录音区分时,可以通过该接口判断当前播放的是录音文件夹还是非录音文件夹 */ /*----------------------------------------------------------------------------*/ bool music_player_get_record_play_status(struct music_player *player_hd) { if (player_hd) { char *logo = dev_manager_get_logo(player_hd->dev); if (logo) { char *str = strstr(logo, "_rec"); if (str) { return true; } } } return false; } /*----------------------------------------------------------------------------*/ /**@brief music_player从设备列表里面往前或往后找设备,并且过滤掉指定字符串的设备 @param flit:过滤字符串, 查找设备时发现设备logo包含这个字符串的会被过滤 direct:查找方向, 1:往后, 0:往前 @return 查找到符合条件的设备逻辑盘符, 找不到返回NULL @note */ /*----------------------------------------------------------------------------*/ char *music_player_get_dev_flit(struct music_player *player_hd, char *flit, u8 direct) { if (player_hd) { u32 counter = 0; struct __dev *dev = player_hd->dev; u32 dev_total = dev_manager_get_total(1); if (dev_manager_online_check(player_hd->dev, 1) == 1) { if (dev_total > 1) { while (1) { if (direct) { dev = dev_manager_find_next(dev, 1); } else { dev = dev_manager_find_prev(dev, 1); } if (dev) { char *logo = dev_manager_get_logo(dev); if (flit) { char *str = strstr(logo, flit); if (!str) { return logo; } counter++; if (counter >= (dev_total - 1)) { break; } } else { return logo; } } else { break; } } } } } return NULL; } /*----------------------------------------------------------------------------*/ /**@brief music_player解码停止 @param fsn_release: 1:释放扫盘句柄 0:不释放扫盘句柄 @return @note 如果释放了扫盘句柄,需要重新扫盘,否则播放失败 */ /*----------------------------------------------------------------------------*/ void music_player_stop(struct music_player *player_hd, u8 fsn_release) { if (player_hd == NULL) { return ; } #if TCFG_USER_EMITTER_ENABLE if (bt_emitter_get_curr_channel_state()) { bt_emitter_pp(0); } #endif #if (defined(TCFG_LRC_LYRICS_ENABLE) && (TCFG_LRC_LYRICS_ENABLE)) extern void lrc_set_analysis_flag(u8 flag); lrc_set_analysis_flag(0); #endif //停止解码 music_file_player_stop(); if (player_hd->file) { fclose(player_hd->file); player_hd->file = NULL; } if (player_hd->lrc_file) { fclose(player_hd->lrc_file); player_hd->lrc_file = NULL; } if (fsn_release && player_hd->fsn) { //根据播放情景, 通过设定flag决定是否需要释放fscan, 释放后需要重新扫盘!!! fscan_release(player_hd->fsn); player_hd->fsn = NULL; } //如果开启把vm配置项暂存到ram的功能,则不需要定期整理vm,增加操作flash的时间 if (get_vm_ram_storage_enable() == FALSE) { //检查整理VM vm_check_all(0); } } /*----------------------------------------------------------------------------*/ /**@brief music_player设置播放循环模式 @param mode:循环模式 FCYCLE_ALL FCYCLE_ONE FCYCLE_FOLDER FCYCLE_RANDOM @return 循环模式 @note */ /*----------------------------------------------------------------------------*/ int music_player_set_repeat_mode(struct music_player *player_hd, u8 mode) { if (player_hd) { if (mode >= FCYCLE_MAX) { return -1; } app_var.cycle_mode = mode; if (player_hd->fsn) { player_hd->fsn->cycle_mode = mode; log_i("cycle_mode = %d\n", mode); local_irq_disable(); save_mode_cnt = 0; if (save_mode_timer == 0) { save_mode_timer = sys_timer_add(NULL, music_player_mode_save_do, 1000); } local_irq_enable(); return mode; } } return -1; } /*----------------------------------------------------------------------------*/ /**@brief music_player切换循环模式 @param @return 循环模式 @note */ /*----------------------------------------------------------------------------*/ int music_player_change_repeat_mode(struct music_player *player_hd) { if (player_hd) { app_var.cycle_mode++; if (app_var.cycle_mode >= FCYCLE_MAX) { app_var.cycle_mode = FCYCLE_LIST; } return music_player_set_repeat_mode(player_hd, app_var.cycle_mode); } return -1; } /*----------------------------------------------------------------------------*/ /**@brief music_player删除当前播放文件,并播放下一曲 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_delete_playing_file(struct music_player *player_hd) { if (player_hd && player_hd->file) { //获取当前播放文件序号, 文件删除之后, 播放下一曲 int err = 0; int cur_file = player_hd->fsn->file_counter; char *cur_dev = dev_manager_get_logo(player_hd->dev); music_file_player_stop(); err = fdelete(player_hd->file); if (err) { log_info("[%s, %d] fail!!, replay cur file\n", __FUNCTION__, __LINE__); } else { log_info("[%s, %d] ok, play next file\n", __FUNCTION__, __LINE__); player_hd->file = NULL; player_hd->dev = NULL;//目的重新扫盘, 更新文件总数 return music_player_play_by_number(player_hd, cur_dev, cur_file); } } return MUSIC_PLAYER_ERR_NULL; } /*----------------------------------------------------------------------------*/ /**@brief music_player播放上一曲 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_prev_cycle_single_dev(struct music_player *player_hd) { //close player first music_player_stop(player_hd, 0); //check dev, 检查设备是否有掉线 if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //不需要重新找设备、扫盘 if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_PREV_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);//选择上一曲 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } int music_player_play_prev(struct music_player *player_hd) { int err; #if (MUSIC_PLAYER_CYCLE_ALL_DEV_EN) u32 cur_file = player_hd->fsn->file_counter; if ((music_player_get_record_play_status(player_hd) == false) && (app_var.cycle_mode == FCYCLE_ALL) && (cur_file == 1) && (dev_manager_get_total(1) > 1)) { char *logo = music_player_get_dev_flit(player_hd, "_rec", 0); err = music_player_play_last_file(player_hd, logo); return err; } #endif err = music_player_play_prev_cycle_single_dev(player_hd); return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player播放下一曲 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_next_cycle_single_dev(struct music_player *player_hd) { //close player first music_player_stop(player_hd, 0); //check dev, 检查设备是否有掉线 if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //不需要重新找设备、扫盘 if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_NEXT_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);//选择下一曲 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } int music_player_play_next(struct music_player *player_hd) { int err; #if (MUSIC_PLAYER_CYCLE_ALL_DEV_EN) u32 cur_file = player_hd->fsn->file_counter; if ((music_player_get_record_play_status(player_hd) == false) && (app_var.cycle_mode == FCYCLE_ALL) && (cur_file >= player_hd->fsn->file_number) && (dev_manager_get_total(1) > 1)) { char *logo = music_player_get_dev_flit(player_hd, "_rec", 1); err = music_player_play_first_file(player_hd, logo); return err; } #endif err = music_player_play_next_cycle_single_dev(player_hd); return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player播放第一曲 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_first_file(struct music_player *player_hd, char *logo) { if (logo == NULL) { music_player_stop(player_hd, 0); if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //没有指定设备不需要找设备, 不需要扫描 } else { music_player_stop(player_hd, 1); player_hd->dev = dev_manager_find_spec(logo, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); } if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_FIRST_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player播放最后一曲 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_last_file(struct music_player *player_hd, char *logo) { if (player_hd == NULL) { return MUSIC_PLAYER_ERR_PARM; } if (logo == NULL) { music_player_stop(player_hd, 0); if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //没有指定设备不需要找设备, 不需要扫描 } else { music_player_stop(player_hd, 1); player_hd->dev = dev_manager_find_spec(logo, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); } if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_LAST_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player自动播放下一曲 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_auto_next(struct music_player *player_hd) { if (player_hd == NULL) { return MUSIC_PLAYER_ERR_PARM; } //close player first music_player_stop(player_hd, 0); //get dev, 检查设备是否有掉线 if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //不需要重新找设备、扫盘 if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_AUTO_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);//选择自动下一曲 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player上一个文件夹 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_folder_prev(struct music_player *player_hd) { if (player_hd == NULL) { return MUSIC_PLAYER_ERR_PARM; } //close player first music_player_stop(player_hd, 0); //get dev, 检查设备是否有掉线 if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //不需要重新找设备、扫盘 if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_PREV_FOLDER_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);//选择播放上一个文件夹 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } #if (MUSIC_PLAYER_PLAY_FOLDER_PREV_FIRST_FILE_EN) struct ffolder folder_info = {0}; if (fget_folder(player_hd->fsn, &folder_info)) { log_e("folder info err!!\n"); return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //先关掉文件 fclose(player_hd->file); //播放文件夹第一首 player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_NUMBER, folder_info.fileStart, player_hd->parm.scan_cb); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } #endif //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player下一个文件夹 @param @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_folder_next(struct music_player *player_hd) { if (player_hd == NULL) { return MUSIC_PLAYER_ERR_PARM; } //close player first music_player_stop(player_hd, 0); //get dev, 检查设备是否有掉线 if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //不需要重新找设备、扫盘 if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_NEXT_FOLDER_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);///选择播放上一个文件夹 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player上一个设备 @param bp:断点信息 @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_devcie_prev(struct music_player *player_hd, struct __breakpoint *bp) { if (player_hd == NULL) { return MUSIC_PLAYER_ERR_PARM; } //close player first music_player_stop(player_hd, 1); //get dev player_hd->dev = dev_manager_find_prev(player_hd->dev, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } //get fscan player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, (const char *)scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } int err = 0; if (bp) { player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_SCLUST, bp->sclust, (struct __scan_callback *)player_hd->parm.scan_cb);//根据文件簇号查找断点文件 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } err = music_player_decode_start(player_hd, player_hd->file, &(bp->dbp)); } else { player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_FIRST_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } err = music_player_decode_start(player_hd, player_hd->file, 0); } if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player下一个设备 @param bp:断点信息 @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_devcie_next(struct music_player *player_hd, struct __breakpoint *bp) { if (player_hd == NULL) { return MUSIC_PLAYER_ERR_PARM; } //close player first music_player_stop(player_hd, 1); //get dev player_hd->dev = dev_manager_find_next(player_hd->dev, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } //get fscan player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } int err = 0; if (bp) { player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_SCLUST, bp->sclust, (struct __scan_callback *)player_hd->parm.scan_cb);//根据文件簇号查找断点文件 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } err = music_player_decode_start(player_hd, player_hd->file, &(bp->dbp)); } else { player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_FIRST_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);//选择第一个文件播放 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } err = music_player_decode_start(player_hd, player_hd->file, 0); } if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player断点播放指定设备 @param logo:逻辑盘符,如:sd0/sd1/udisk0 bp:断点信息 @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_by_breakpoint(struct music_player *player_hd, char *logo, struct __breakpoint *bp) { u32 bp_flag = 1; if (bp == NULL) { return music_player_play_first_file(player_hd, logo); } if (logo == NULL) { music_player_stop(player_hd, 0); if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //没有指定设备不需要找设备, 不需要扫描 } else { music_player_stop(player_hd, 1); player_hd->dev = dev_manager_find_spec(logo, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } bp_flag = 0; set_bp_info(bp->sclust, bp->fsize, &bp_flag); //断点若有效把bp_flag置1,注意后面要用put_bp_info释放资源 player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); } if (player_hd->fsn == NULL) { put_bp_info(); return MUSIC_PLAYER_ERR_FSCAN; } if (!bp_flag) { //断点无效 put_bp_info(); return MUSIC_PLAYER_ERR_PARM; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_SCLUST, bp->sclust, (struct __scan_callback *)player_hd->parm.scan_cb);//根据文件簇号查找断点文件 put_bp_info(); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } struct vfs_attr attr = {0}; fget_attrs(player_hd->file, &attr); if (bp->fsize != attr.fsize) { return MUSIC_PLAYER_ERR_PARM; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, &(bp->dbp)); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player序号播放指定设备 @param logo:逻辑盘符,如:sd0/sd1/udisk0 number:指定播放序号 @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_by_number(struct music_player *player_hd, char *logo, u32 number) { char *cur_logo = dev_manager_get_logo(player_hd->dev); if (logo == NULL || (cur_logo && logo && (0 == strcmp(logo, cur_logo)))) { music_player_stop(player_hd, 0); if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //没有指定设备不需要找设备, 不需要扫描 } else { music_player_stop(player_hd, 1); player_hd->dev = dev_manager_find_spec(logo, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); } if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_NUMBER, number, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player簇号播放指定设备 @param logo:逻辑盘符,如:sd0/sd1/udisk0 sclust:指定播放簇号 @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_by_sclust(struct music_player *player_hd, char *logo, u32 sclust) { char *cur_logo = dev_manager_get_logo(player_hd->dev); if (logo == NULL || (cur_logo && logo && (0 == strcmp(logo, cur_logo)))) { music_player_stop(player_hd, 0); if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //没有指定设备不需要找设备, 不需要扫描 } else { music_player_stop(player_hd, 1); player_hd->dev = dev_manager_find_spec(logo, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); } if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_SCLUST, sclust, (struct __scan_callback *)player_hd->parm.scan_cb);//根据簇号查找文件 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player路径播放指定设备 @param logo:逻辑盘符,如:sd0/sd1/udisk0, 设置为NULL,为默认当前播放设备 path:指定播放路径 @return 播放错误码 @note */ /*----------------------------------------------------------------------------*/ int music_player_play_by_path(struct music_player *player_hd, char *logo, const char *path) { if (path == NULL) { return MUSIC_PLAYER_ERR_POINT; } if (logo == NULL) { music_player_stop(player_hd, 0); if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } //没有指定设备不需要找设备, 不需要扫描 } else { music_player_stop(player_hd, 1); player_hd->dev = dev_manager_find_spec(logo, 1); if (player_hd->dev == NULL) { return MUSIC_PLAYER_ERR_DEV_NOFOUND; } player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); } if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } //get file player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_PATH, (int)path, (struct __scan_callback *)player_hd->parm.scan_cb);//根据簇号查找文件 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder int err = music_player_decode_start(player_hd, player_hd->file, 0); if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); } return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player录音区分切换播放 @param logo:逻辑盘符,如:sd0/sd1/udisk0, 设置为NULL,为默认当前播放设备 bp:断点信息 @return 播放错误码 @note 通过指定设备盘符,接口内部通过解析盘符是否"_rec" 来确定是切换到录音播放设备还是非录音播放设备 */ /*----------------------------------------------------------------------------*/ int music_player_play_record_folder(struct music_player *player_hd, char *logo, struct __breakpoint *bp) { int err = MUSIC_PLAYER_ERR_NULL; #if (TCFG_RECORD_FOLDER_DEV_ENABLE) char rec_dev_logo[16] = {0}; char music_dev_logo[16] = {0}; u8 rec_play = 0; struct __dev *dev; if (logo == NULL) { logo = dev_manager_get_logo(player_hd->dev); if (logo == NULL) { return MUSIC_PLAYER_ERR_RECORD_DEV; } } //判断是否是录音设备 char *str = strstr(logo, "_rec"); if (str == NULL) { //是非录音设备,切换到录音设备播放 sprintf(rec_dev_logo, "%s%s", logo, "_rec"); dev = dev_manager_find_spec(rec_dev_logo, 1); logo = rec_dev_logo; rec_play = 1; } else { //录音设备,切换到音乐设备播放 strncpy(music_dev_logo, logo, strlen(logo) - strlen(str)); log_i("music_dev_logo = %s, logo = %s, str = %s, len = %d\n", music_dev_logo, logo, str, strlen(logo) - strlen(str)); dev = dev_manager_find_spec(music_dev_logo, 1); logo = music_dev_logo; rec_play = 0; } if (dev == NULL) { return MUSIC_PLAYER_ERR_RECORD_DEV; } ///需要扫盘 struct vfscan *fsn = file_manager_scan_disk(dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); if (fsn == NULL) { dev_manager_set_valid(dev, 0); return MUSIC_PLAYER_ERR_RECORD_DEV; } else { music_player_stop(player_hd, 1); player_hd->dev = dev; player_hd->fsn = fsn; } //get file if (bp) { player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_BY_SCLUST, bp->sclust, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder err = music_player_decode_start(player_hd, player_hd->file, &bp->dbp); } else { player_hd->file = file_manager_select(player_hd->dev, player_hd->fsn, FSEL_FIRST_FILE, 0, (struct __scan_callback *)player_hd->parm.scan_cb);//播放录音文件夹第一个文件 if (player_hd->file == NULL) { return MUSIC_PLAYER_ERR_FILE_NOFOUND; } //start decoder err = music_player_decode_start(player_hd, player_hd->file, 0);//录音文件夹不支持断点播放 } if (err == MUSIC_PLAYER_SUCC) { //选定新设备播放成功后,需要激活当前设备 dev_manager_set_active(player_hd->dev); log_i("[%s %d] %s devcie play ok\n", __FUNCTION__, __LINE__, logo); } #endif return err; } /*----------------------------------------------------------------------------*/ /**@brief music_player扫盘 @param @return 播放错误码 @note 音乐模式下盘符曲目发生变化时 调用接口重新扫盘当前设备 */ /*----------------------------------------------------------------------------*/ int music_player_scan_disk(struct music_player *player_hd) { char *logo = NULL; if (!player_hd) { return MUSIC_PLAYER_ERR_PARM; } music_player_stop(player_hd, 1); //check dev, 检查设备是否有掉线 if (dev_manager_online_check(player_hd->dev, 1) == 0) { return MUSIC_PLAYER_ERR_DEV_OFFLINE; } player_hd->fsn = file_manager_scan_disk(player_hd->dev, NULL, scan_parm, app_var.cycle_mode, (struct __scan_callback *)player_hd->parm.scan_cb); if (player_hd->fsn == NULL) { return MUSIC_PLAYER_ERR_FSCAN; } return MUSIC_PLAYER_ERR_NULL; } int music_player_lrc_analy_start(struct music_player *player_hd) { #if (defined(TCFG_LRC_LYRICS_ENABLE) && (TCFG_LRC_LYRICS_ENABLE)) extern bool lrc_analysis_api(FILE * file, FILE **newFile); extern void lrc_set_analysis_flag(u8 flag); log_i("music lrc analys start:"); if (player_hd && player_hd->file) { if (lrc_analysis_api(player_hd->file, &(player_hd->lrc_file))) { lrc_set_analysis_flag(1); return 0; } else { lrc_set_analysis_flag(0); return -1; } } #endif return -1; }