This commit is contained in:
lmx
2025-10-29 13:10:02 +08:00
commit 49a07fa419
2284 changed files with 642060 additions and 0 deletions

View File

@ -0,0 +1,754 @@
#include "system/includes.h"
#include "music/music_player.h"
#include "music/breakpoint.h"
#include "app_action.h"
#include "app_main.h"
#include "earphone.h"
#include "key_event_deal.h"
#include "audio_config.h"
#include "bt_background.h"
#include "default_event_handler.h"
#include "app_online_cfg.h"
#include "user_cfg.h"
#include "tone_player.h"
#include "app_task.h"
#include "earphone.h"
#include "update.h"
#include "app_power_manage.h"
#include "app_charge.h"
#define LOG_TAG_CONST MUSIC
#define LOG_TAG "[MUSIC]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_APP_MUSIC_EN
#define VALUE_NULL 0
//模式idle状态
static volatile u8 is_music_active = 0;
///模式参数结构体
struct __music_task_parm {
u8 type;
int val;
};
///music模式控制结构体
struct __music {
struct __music_task_parm task_parm;
u16 file_err_counter;//错误文件统计
u8 file_play_direct;//0:下一曲, 1上一曲
u8 scandisk_break;//扫描设备打断标志
char device_tone_dev[16];
#if SD_BAUD_RATE_CHANGE_WHEN_SCAN
u32 old_speed;
#endif
};
struct __music music_hdl = {0};
#define __this (&music_hdl)
static struct __breakpoint *breakpoint = NULL;
static const u8 music_key_table[][KEY_EVENT_MAX] = {
// SHORT LONG HOLD
// UP DOUBLE TRIPLE
{
KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD,
KEY_NULL, KEY_MODE_SWITCH, KEY_NULL
},
{
KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP,
KEY_NULL, KEY_NULL, KEY_NULL
},
{
KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN,
KEY_NULL, KEY_NULL, KEY_NULL
},
};
//*----------------------------------------------------------------------------*/
/**@brief 检测能否进入低功耗
@param 无
@return 无
@note 无
@note 放在按键事件处理后
*/
/*----------------------------------------------------------------------------*/
static void music_powerdown_enter_check(void)
{
u8 music_play_status = 0;
music_play_status = music_player_get_play_status();
if ((is_music_active == 1) && (music_play_status == FILE_DEC_STATUS_PAUSE)) {
is_music_active = 0;
}
/* log_info(">>>>>>>>>>>>>>>enter music_play_status = %d\n", music_play_status); */
}
//*----------------------------------------------------------------------------*/
/**@brief 检测能否退出低功耗
@param 无
@return 无
@note 无
@note 放在按键事件处理前
*/
/*----------------------------------------------------------------------------*/
static void music_powerdown_exit_check(void)
{
u8 music_play_status = 0;
music_play_status = music_player_get_play_status();
//非暂停的自定义按键事件, 把进低功耗的定时器删除
if (music_play_status == FILE_DEC_STATUS_PAUSE) {
if (is_music_active == 0) {
is_music_active = 1;
}
}
/* log_info(">>>>>>>>>>>>>>>exit music_play_status = %d\n", music_play_status); */
}
//*----------------------------------------------------------------------------*/
/**@brief music 解码成功回调
@param priv:私有参数, parm:暂时未用
@return
@note 此处可以做一些用户操作, 如断点保存, 显示, 获取播放信息等
*/
/*----------------------------------------------------------------------------*/
static void music_player_play_success(void *priv, int parm)
{
char *logo = music_player_get_dev_cur();
log_info("\n\n----------------music_player_play_success----------------------\n");
log_info("cur dev = %s\n", logo);
log_info("total dev = %d\n", dev_manager_get_total(1));
log_info("cur filenum = %d\n", music_player_get_file_cur());
log_info("totol filenum = %d\n", music_player_get_file_total());
log_info("totol time = %d\n", music_player_get_dec_total_time());
log_info("sclust = %d\n", music_player_get_file_sclust());
log_info("dir_cur = %d\n", music_player_get_dir_cur());
log_info("dir_total = %d\n", music_player_get_dir_total());
log_info("file indir = %d\n", music_player_get_fileindir_number());
log_info("\n");
///save breakpoint, 只保存文件信息
if (music_player_get_playing_breakpoint(breakpoint, 0) == true) {
breakpoint_vm_write(breakpoint, logo);
}
}
//*----------------------------------------------------------------------------*/
/**@brief music 发送自定义按键消息
@param msg:按键类型; value:发送的值
@return 0:发送正常 -1:发送失败
@note 虚拟按键消息
*/
/*----------------------------------------------------------------------------*/
static int app_music_task_put_key_msg(int msg, int value)
{
if (app_get_curr_task() != APP_MUSIC_TASK) {
//不在音乐模式不发自定义按键消息
log_w("custom msg invalid!");
return -1;
}
struct sys_event e;
e.type = SYS_KEY_EVENT;
e.u.key.event = msg;
e.u.key.value = value;
e.arg = (void *)DEVICE_EVENT_FROM_CUSTOM;
sys_event_notify(&e);
return 0;
}
//*----------------------------------------------------------------------------*/
/**@brief music 解码结束回调处理
@param
@return
@note 此处统一将错误通过消息的方式发出, 在key msg中统一响应
*/
/*----------------------------------------------------------------------------*/
static void music_player_play_end(void *priv, int parm)
{
log_info("music_player_play_end\n");
///这里推出消息, 目的是在music主流程switch case统一入口
app_music_task_put_key_msg(KEY_MUSIC_PLAYER_END, parm);
}
//*----------------------------------------------------------------------------*/
/**@brief music 解码错误回调
@param
@return
@note 此处统一将错误通过消息的方式发出, 在key msg中统一响应
*/
/*----------------------------------------------------------------------------*/
static void music_player_decode_err(void *priv, int parm)
{
log_info("music_player_decode_err\n");
///这里推出消息, 目的是在music主流程switch case统一入口
app_music_task_put_key_msg(KEY_MUSIC_PLAYER_DEC_ERR, parm);
}
static const struct __player_cb music_player_callback = {
.start = music_player_play_success,
.end = music_player_play_end,
.err = music_player_decode_err,
// .fsn_break = music_player_scandisk_break,
};
static const struct __scan_callback scan_cb = {
.enter = NULL,
.exit = NULL,
.scan_break = NULL,
};
//*----------------------------------------------------------------------------*/
/**@brief music 模式初始化处理
@param 无
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void music_task_start()
{
char *log = NULL;
log_info("music task start!!!!!\n");
///时钟初始化
clk_set("sys", CONFIG_MUSIC_DEC_CLOCK);
///按键使能
sys_key_event_enable();
//关闭自动关机
sys_auto_shut_down_disable();
///播放器初始化
struct __player_parm parm = {0};
parm.cb = &music_player_callback;
parm.scan_cb = &scan_cb;
music_player_creat(NULL, &parm);
music_player_set_repeat_mode(FCYCLE_ALL);
///获取断点句柄, 后面所有断点读/写都需要用到
breakpoint = breakpoint_handle_creat();
///初始化一些参数
__this->file_err_counter = 0;
__this->file_play_direct = 0;
__this->scandisk_break = 0;
is_music_active = 1;
}
//*----------------------------------------------------------------------------*/
/**@brief 开始播歌
@param 无
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void music_player_play_start(void)
{
app_music_task_put_key_msg(KEY_MUSIC_PLAYER_START, VALUE_NULL);
}
static void music_save_breakpoint(int save_dec_bp)
{
char *logo = music_player_get_dev_cur();
///save breakpoint, 只保存文件信息
if (music_player_get_playing_breakpoint(breakpoint, save_dec_bp) == true) {
breakpoint_vm_write(breakpoint, logo);
}
}
//*----------------------------------------------------------------------------*/
/**@brief music 模式退出处理
@param 无
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void music_task_close()
{
music_save_breakpoint(1);
music_player_stop(1);
breakpoint_handle_destroy(&breakpoint);
music_player_destroy();
memset(__this, 0, sizeof(struct __music));
is_music_active = 0;
}
//*----------------------------------------------------------------------------*/
/**@brief 恢复音乐模式
@param 无
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void music_task_resume(void)
{
music_task_start();
music_player_play_start();
}
//*----------------------------------------------------------------------------*/
/**@brief 清除自定义按键消息
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
static void custom_event_clr(void)
{
struct sys_event clear_key_event = {
.type = SYS_KEY_EVENT,
.arg = (void *)DEVICE_EVENT_FROM_CUSTOM,
};
sys_key_event_disable();
sys_event_clear(&clear_key_event);
}
//*----------------------------------------------------------------------------*/
/**@brief music 在线检测 切换模式判断使用
@param 无
@return 1 设备在线 0 设备不在线
@note
*/
/*----------------------------------------------------------------------------*/
int music_app_check(void)
{
log_info("music_app_check");
if (dev_manager_get_total(1)) {
return true;
}
return false;
}
//*----------------------------------------------------------------------------*/
/**@brief music 模式解码错误处理
@param err:错误码详细错误码描述请看music_player错误码表枚举
@return
@note
*/
/*----------------------------------------------------------------------------*/
void music_player_err_deal(int err)
{
u16 msg = KEY_NULL;
char *logo = NULL;
if (err != MUSIC_PLAYER_ERR_NULL && err != MUSIC_PLAYER_SUCC) {
log_e("music player err = %d\n", err);
}
switch (err) {
case MUSIC_PLAYER_SUCC:
__this->file_err_counter = 0;
break;
case MUSIC_PLAYER_ERR_NULL:
break;
case MUSIC_PLAYER_ERR_POINT:
case MUSIC_PLAYER_ERR_NO_RAM:
msg = KEY_MUSIC_PLAYER_QUIT;//退出音乐模式
break;
case MUSIC_PLAYER_ERR_DECODE_FAIL:
if (__this->file_err_counter >= music_player_get_file_total()) {
__this->file_err_counter = 0;
dev_manager_set_valid_by_logo(music_player_get_dev_cur(), 0);///将设备设置为无效设备
if (dev_manager_get_total(1) == 0) {//参数为1 :获取所有有效设备 参数0获取所有设备
msg = KEY_MUSIC_PLAYER_QUIT;//没有设备了,退出音乐模式
} else {
msg = KEY_MUSIC_AUTO_NEXT_DEV;///所有文件都是错误的, 切换到下一个设备
}
} else {
__this->file_err_counter ++;
if (__this->file_play_direct == 0) {
msg = KEY_MUSIC_NEXT;//播放下一曲
} else {
msg = KEY_MUSIC_PREV;//播放上一曲
}
}
break;
case MUSIC_PLAYER_ERR_DEV_NOFOUND:
if (dev_manager_get_total(1) == 0) {//参数为1 :获取所有有效设备 参数0获取所有设备
msg = KEY_MUSIC_PLAYER_QUIT;///没有设备在线, 退出音乐模式
} else {
msg = KEY_MUSIC_PLAYER_START;///没有找到指定设备, 播放之前的活动设备
}
break;
case MUSIC_PLAYER_ERR_FSCAN:
///需要结合music_player_scandisk_break中处理的标志位处理
if (__this->scandisk_break) {
__this->scandisk_break = 0;
///此处不做任何处理, 打断的事件已经重发, 由重发事件执行后续处理
break;
}
case MUSIC_PLAYER_ERR_DEV_READ:
case MUSIC_PLAYER_ERR_DEV_OFFLINE:
log_e("MUSIC_PLAYER_ERR_DEV_OFFLINE \n");
logo = music_player_get_dev_cur();
if (dev_manager_online_check_by_logo(logo, 1)) {
///如果错误失败在线, 并且是播放过程中产生的,先记录下断点
if (music_player_get_playing_breakpoint(breakpoint, 1) == true) {
music_player_stop(0);//先停止防止下一步操作VM卡顿
breakpoint_vm_write(breakpoint, logo);
}
if (err == MUSIC_PLAYER_ERR_FSCAN) {
dev_manager_set_valid_by_logo(logo, 0);///将设备设置为无效设备
} else {
//针对读错误, 因为时间推到应用层有延时导致下一个模式判断不正常, 此处需要将设备卸载
dev_manager_unmount(dev_manager_get_logo(dev_manager_find_active(0)));
}
}
if (dev_manager_get_total(1) == 0) {
msg = KEY_MUSIC_PLAYER_QUIT;///没有设备在线, 退出音乐模式
} else {
msg = KEY_MUSIC_AUTO_NEXT_DEV;///切换设备
}
break;
case MUSIC_PLAYER_ERR_FILE_NOFOUND:
///查找文件有扫盘的可能也需要结合music_player_scandisk_break中处理的标志位处理
if (__this->scandisk_break) {
__this->scandisk_break = 0;
///此处不做任何处理, 打断的事件已经重发, 由重发事件执行后续处理
break;
}
case MUSIC_PLAYER_ERR_PARM:
logo = music_player_get_dev_cur();
if (dev_manager_online_check_by_logo(logo, 1)) {
if (music_player_get_file_total()) {
msg = KEY_MUSIC_PLAYER_PLAY_FIRST;///有文件,播放第一个文件
break;
}
}
if (dev_manager_get_total(1) == 0) {
msg = KEY_MUSIC_PLAYER_QUIT;//没有设备了,退出音乐模式
} else {
msg = KEY_MUSIC_AUTO_NEXT_DEV;
}
break;
case MUSIC_PLAYER_ERR_FILE_READ://文件读错误
msg = KEY_MUSIC_NEXT;//播放下一曲
break;
}
if (msg != KEY_NULL) {
app_music_task_put_key_msg(msg, VALUE_NULL);
}
}
//*----------------------------------------------------------------------------*/
/**@brief music 模式按键处理
@param 按键消息
@return
@note
*/
/*----------------------------------------------------------------------------*/
static int app_music_key_event_handler(struct sys_event *event)
{
int ret = true;
int err = MUSIC_PLAYER_ERR_NULL;
u8 vol, auto_next_dev;
int mode ;
char *logo = NULL;
int key_event = 0;
struct key_event *key = &event->u.key;
if (event->arg == DEVICE_EVENT_FROM_KEY) {
key_event = music_key_table[key->value][key->event];//物理按键事件
} else {
key_event = key->event;//软件按键事件
}
log_info("music task msg = %d\n", key_event);
music_powerdown_exit_check();
switch (key_event) {
case KEY_MUSIC_PLAYER_START:
log_info("KEY_MUSIC_PLAYER_START !!\n");
///断点播放活动设备
logo = dev_manager_get_logo(dev_manager_find_active(1));
if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) {
if (music_player_get_dev_cur() && logo) {
///播放的设备跟当前活动的设备是同一个设备,不处理
if (0 == strcmp(logo, music_player_get_dev_cur())) {
log_w("the same dev!!\n");
break;
}
}
}
if (true == breakpoint_vm_read(breakpoint, logo)) {
err = music_player_play_by_breakpoint(logo, breakpoint);
} else {
err = music_player_play_first_file(logo);
}
break;
///播放器退出处理
case KEY_MUSIC_PLAYER_QUIT:
log_info("KEY_MUSIC_PLAYER_QUIT !!\n");
app_task_switch_next();
break;
///结束消息处理
case KEY_MUSIC_PLAYER_END:
log_info("KEY_MUSIC_PLAYER_END\n");
err = music_player_end_deal(key->value);
break;
//播放器解码错误处理
case KEY_MUSIC_PLAYER_DEC_ERR:
err = music_player_decode_err_deal(key->value);
break;
///播放执行类消息
case KEY_MUSIC_PP:
log_info("KEY_MUSIC_PP\n");
err = music_player_pp();
log_info("=============================================%d\n", music_player_get_play_status());
break;
case KEY_MUSIC_PLAYER_AUTO_NEXT:
log_info("KEY_MUSIC_PLAYER_AUTO_NEXT\n");
err = music_player_play_auto_next();
break;
case KEY_MUSIC_PLAYER_PLAY_FIRST:
log_info("KEY_MUSIC_PLAYER_PLAY_FIRST\n");
err = music_player_play_first_file(NULL);
break;
case KEY_MUSIC_PREV:
log_info("KEY_MUSIC_PREV\n");
__this->file_play_direct = 1;
err = music_player_play_prev();
break;
case KEY_MUSIC_NEXT:
log_info("KEY_MUSIC_NEXT\n");
__this->file_play_direct = 0;
err = music_player_play_next();
break;
case KEY_MUSIC_PLAYE_PREV_FOLDER:
log_info("KEY_MUSIC_PLAYE_PREV_FOLDER\n");
err = music_player_play_folder_prev();
break;
case KEY_MUSIC_PLAYE_NEXT_FOLDER:
log_info("KEY_MUSIC_PLAYE_NEXT_FOLDER\n");
err = music_player_play_folder_next();
break;
case KEY_MUSIC_AUTO_NEXT_DEV:
case KEY_MUSIC_CHANGE_DEV:
log_info("KEY_MUSIC_CHANGE_DEV\n");
auto_next_dev = ((key_event == KEY_MUSIC_AUTO_NEXT_DEV) ? 1 : 0);
logo = music_player_get_dev_next(auto_next_dev);
log_info("next dev = %s\n", logo);
if (logo == NULL) { ///找不到下一个设备,不响应设备切换
break;
}
///切换设备前先保存一下上一个设备的断点信息,包括文件和解码信息
if (music_player_get_playing_breakpoint(breakpoint, 1) == true) {
music_player_stop(0);//先停止防止下一步操作VM卡顿
breakpoint_vm_write(breakpoint, music_player_get_dev_cur());
}
if (true == breakpoint_vm_read(breakpoint, logo)) {
err = music_player_play_by_breakpoint(logo, breakpoint);
} else {
err = music_player_play_first_file(logo);
}
break;
case KEY_MUSIC_PLAYE_BY_DEV_FILENUM:
log_info("KEY_MUSIC_PLAYE_BY_DEV_FILENUM, file_number = %d\n", key->value);
logo = dev_manager_get_logo(dev_manager_find_active(1));
err = music_player_play_by_number(logo, key->value);
break;
case KEY_MUSIC_PLAYE_BY_DEV_SCLUST:
log_info("KEY_MUSIC_PLAYE_BY_DEV_SCLUST\n");
logo = dev_manager_get_logo(dev_manager_find_active(1));
err = music_player_play_by_sclust(logo, key->value);
break;
case KEY_MUSIC_PLAYE_BY_DEV_PATH:
log_info("KEY_MUSIC_PLAYE_BY_DEV_PATH\n");
err = music_player_play_by_path((char *)"udisk0", "/sin.wav");///this is a demo
break;
///非播放执行类消息
case KEY_MUSIC_FF:
log_info("KEY_MUSIC_FF\n");
music_player_ff(3);
break;
case KEY_MUSIC_FR:
log_info("KEY_MUSIC_FR\n");
music_player_fr(3);
break;
case KEY_MUSIC_CHANGE_REPEAT:
log_info("KEY_MUSIC_CHANGE_REPEAT\n");
mode = music_player_change_repeat_mode();
break;
case KEY_MUSIC_DELETE_FILE:
log_info("KEY_MUSIC_DELETE_FILE\n");
err = music_player_delete_playing_file();
break;
case KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH:
/* file_dec_ab_repeat_switch(); */
break;
case KEY_MODE_SWITCH:
log_info("KEY_MUSIC_SWITCH\n");
app_task_switch_next();
break;
case KEY_VOL_UP:
log_info("KEY_VOL_UP\n");
if (!tone_get_status()) {
app_audio_volume_up(1);
log_info("vol+: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
}
if (app_audio_get_volume(APP_AUDIO_CURRENT_STATE) == app_audio_get_max_volume()) {
if (tone_get_status() == 0) {
#if TCFG_MAX_VOL_PROMPT
STATUS *p_tone = get_tone_config();
tone_play_index(p_tone->max_vol, 0);
#endif
}
}
break;
case KEY_VOL_DOWN:
log_info("KEY_VOL_DOWN\n");
app_audio_volume_down(1);
log_info("vol-: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
break;
case KEY_POWEROFF:
case KEY_POWEROFF_HOLD:
app_earphone_key_event_handler(event);
break;
default:
ret = false;
break;
}
music_powerdown_enter_check();
//退出模式后,不做错误处理
if (is_music_active == 0) {
return false;
}
///错误处理
log_info("music play err = %d\n", err);
music_player_err_deal(err);
return false;
}
/*
* 系统事件处理函数
*/
static int event_handler(struct application *app, struct sys_event *event)
{
switch (event->type) {
case SYS_KEY_EVENT:
/*
* 普通按键消息处理
*/
return app_music_key_event_handler(event);
case SYS_BT_EVENT:
/*
* 蓝牙事件处理
*/
break;
case SYS_DEVICE_EVENT:
/*
* 系统设备事件处理
*/
if ((u32)event->arg == DRIVER_EVENT_FROM_SD0) {
if (event->u.dev.event == DEVICE_EVENT_OUT) {
update_clear_result();
music_save_breakpoint(1);
dev_manager_del((char *)event->u.dev.value);
app_task_switch_next();
return true;
}
}
if ((u32)event->arg == DRIVER_EVENT_FROM_SD0) {
#if TCFG_ONLINE_ENABLE
} else if ((u32)event->arg == DEVICE_EVENT_FROM_CI_UART) {
ci_data_rx_handler(CI_UART);
#if TCFG_USER_TWS_ENABLE
} else if ((u32)event->arg == DEVICE_EVENT_FROM_CI_TWS) {
ci_data_rx_handler(CI_TWS);
#endif
#endif
} else if ((u32)event->arg == DEVICE_EVENT_FROM_POWER) {
app_power_event_handler(&event->u.dev);
return true;
} else if ((u32)event->arg == DEVICE_EVENT_FROM_CHARGE) {
app_charge_event_handler(&event->u.dev);
return true;
}
break;
default:
break;
}
default_event_handler(event);
return false;
}
static int state_machine(struct application *app, enum app_state state,
struct intent *it)
{
int err = 0;
int tone_play_err = 0;
switch (state) {
case APP_STA_CREATE: {
log_info("APP_STA_CREATE\n");
//播完提示音再开始播SD卡
tone_play_err = tone_play_with_callback(TONE_MUSIC_MODE, 1, music_player_play_start, NULL);
if (tone_play_err == -EINVAL) {
log_info("tone play err! music_player_play_start!\n");
music_player_play_start();
}
}
break;
case APP_STA_START:
if (!it) {
break;
}
switch (it->action) {
case ACTION_MUSIC_MAIN:
log_info("ACTION_MUSIC_MAIN\n");
music_task_start();
break;
case ACTION_MUSIC_TWS_RX:
break;
}
break;
case APP_STA_PAUSE:
log_info("APP_STA_PAUSE\n");
music_task_close();
break;
case APP_STA_RESUME:
log_info("APP_STA_RESUME\n");
music_task_resume();
break;
case APP_STA_STOP:
log_info("APP_STA_STOP\n");
music_task_close();
break;
case APP_STA_DESTROY:
log_info("APP_STA_DESTROY\n");
custom_event_clr();
break;
}
return err;
}
static const struct application_operation app_music_ops = {
.state_machine = state_machine,
.event_handler = event_handler,
};
/*
* 注册music模式
*/
REGISTER_APPLICATION(app_music) = {
.name = "music",
.action = ACTION_MUSIC_MAIN,
.ops = &app_music_ops,
.state = APP_STA_DESTROY,
};
/*
* 注册idle状态
*/
static u8 music_idle_query(void)
{
return !is_music_active;
}
REGISTER_LP_TARGET(music_lp_target) = {
.name = "music",
.is_idle = music_idle_query,
};
#endif