839 lines
25 KiB
C
839 lines
25 KiB
C
#ifdef SUPPORT_MS_EXTENSIONS
|
|
#pragma bss_seg(".file_player.data.bss")
|
|
#pragma data_seg(".file_player.data")
|
|
#pragma const_seg(".file_player.text.const")
|
|
#pragma code_seg(".file_player.text")
|
|
#endif
|
|
#include "file_player.h"
|
|
#include "fs/resfile.h"
|
|
#include "os/os_api.h"
|
|
#include "system/init.h"
|
|
#include "system/includes.h"
|
|
#include "app_config.h"
|
|
#include "fs/fs.h"
|
|
#include "effects/audio_pitchspeed.h"
|
|
#include "audio_decoder.h"
|
|
#include "jldemuxer.h"
|
|
#include "clock_manager/clock_manager.h"
|
|
#include "audio_config_def.h"
|
|
#include "effects/audio_vbass.h"
|
|
|
|
#if TCFG_APP_MUSIC_EN
|
|
|
|
struct music_file_player_hdl {
|
|
u8 player_id ;
|
|
OS_MUTEX mutex;
|
|
struct list_head head;
|
|
#if FILE_DEC_DEST_PLAY || FILE_DEC_REPEAT_EN
|
|
struct file_player *cur_player ; //当前的音乐播放器句柄
|
|
#endif
|
|
};
|
|
|
|
static struct music_file_player_hdl g_file_player;
|
|
|
|
static int music_file_player_start(struct file_player *);
|
|
const struct stream_file_ops music_file_ops;
|
|
|
|
__attribute__((weak))
|
|
void music_event_to_user(int event, u16 fname_uuid)
|
|
{
|
|
|
|
}
|
|
|
|
void music_player_free(struct file_player *player)
|
|
{
|
|
if (--player->ref == 0) {
|
|
if (player->break_point_flag == 1) {
|
|
free(player->break_point);
|
|
player->break_point = NULL;
|
|
player->break_point_flag = 0;
|
|
}
|
|
free(player);
|
|
#if FILE_DEC_DEST_PLAY || FILE_DEC_REPEAT_EN
|
|
g_file_player.cur_player = NULL;
|
|
#endif
|
|
}
|
|
}
|
|
extern FILE *music_player_get_file_hdl(void);
|
|
extern void music_player_remove_file_hdl(void);
|
|
|
|
extern int music_player_play_auto_next(void);
|
|
static void music_player_callback(void *_player_id, int event)
|
|
{
|
|
struct file_player *player;
|
|
|
|
printf("music_callback: %x, %d\n", event, (u8)_player_id);
|
|
|
|
switch (event) {
|
|
case STREAM_EVENT_START:
|
|
#if AUDIO_VBASS_LINK_VOLUME
|
|
vbass_link_volume();
|
|
#endif
|
|
if (list_empty(&(g_file_player.head))) { //先判断是否为空防止触发异常
|
|
break;
|
|
}
|
|
os_mutex_pend(&g_file_player.mutex, 0);
|
|
player = list_first_entry(&(g_file_player.head), struct file_player, entry);
|
|
if (player->player_id != (u8)_player_id) {
|
|
os_mutex_post(&g_file_player.mutex);
|
|
printf("player_id_not_match: %d\n", player->player_id);
|
|
break;
|
|
}
|
|
os_mutex_post(&g_file_player.mutex);
|
|
if (player->callback) {
|
|
player->callback(player->priv, 0, STREAM_EVENT_START);
|
|
}
|
|
break;
|
|
case STREAM_EVENT_PREEMPTED:
|
|
break;
|
|
case STREAM_EVENT_NEGOTIATE_FAILD:
|
|
case STREAM_EVENT_STOP:
|
|
if (list_empty(&(g_file_player.head))) { //先判断是否为空防止触发异常
|
|
break;
|
|
}
|
|
os_mutex_pend(&g_file_player.mutex, 0);
|
|
player = list_first_entry(&(g_file_player.head), struct file_player, entry);
|
|
if (player->player_id != (u8)_player_id) {
|
|
os_mutex_post(&g_file_player.mutex);
|
|
printf("player_id_not_match: %d\n", player->player_id);
|
|
break;
|
|
}
|
|
//list_del(&player->entry);
|
|
//jlstream_release(player->stream);
|
|
|
|
//if (!list_empty(&(g_file_player.head))) {
|
|
// struct file_player *p = list_first_entry(&(g_file_player.head), struct file_player, entry);
|
|
// music_file_player_start(p);
|
|
//}
|
|
os_mutex_post(&g_file_player.mutex);
|
|
if (player->callback) {
|
|
player->callback(player->priv, player->read_err, STREAM_EVENT_STOP);
|
|
|
|
}
|
|
//music_player_free(player);
|
|
/* int err = music_player_play_auto_next(); */
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int music_file_read(void *file, u8 *buf, int len)
|
|
{
|
|
int offset = 0;
|
|
struct file_player *player = (struct file_player *)file;
|
|
|
|
while (len) {
|
|
if (!player->file) {
|
|
break;
|
|
}
|
|
|
|
int rlen = 0;
|
|
|
|
#if TCFG_DEC_DECRYPT_ENABLE
|
|
u32 addr;
|
|
addr = ftell(player->file);
|
|
rlen = fread(buf + offset, len, 1, player->file);
|
|
if (rlen && (rlen <= len)) {
|
|
cryptanalysis_buff(&player->mply_cipher, buf + offset, addr, rlen); //解密了
|
|
}
|
|
#else
|
|
rlen = fread(buf + offset, len, 1, player->file);
|
|
#endif
|
|
|
|
|
|
if (rlen < 0 || rlen == 0) {
|
|
if (rlen == (-1)) {
|
|
player->read_err = 1; //file err
|
|
} else {
|
|
if (rlen != 0) {
|
|
player->read_err = 2; //dis err
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
player->read_err = 0;
|
|
offset += rlen;
|
|
if ((len -= rlen) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int music_file_seek(void *file, int offset, int fromwhere)
|
|
{
|
|
struct file_player *player = (struct file_player *)file;
|
|
return fseek(player->file, offset, fromwhere);
|
|
}
|
|
|
|
int music_file_flen(void *file)
|
|
{
|
|
struct file_player *player = (struct file_player *)file;
|
|
u32 len = 0;
|
|
if (player->file) {
|
|
len = flen(player->file);
|
|
}
|
|
return len;
|
|
}
|
|
|
|
static int music_file_close(void *file)
|
|
{
|
|
struct file_player *player = (struct file_player *)file;
|
|
|
|
if (player->file) {
|
|
if (music_player_get_file_hdl()) {
|
|
fclose(player->file);
|
|
music_player_remove_file_hdl();
|
|
}
|
|
player->file = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int music_file_get_fmt(void *file, struct stream_fmt *fmt)
|
|
{
|
|
u8 name[16];
|
|
struct file_player *player = (struct file_player *)file;
|
|
|
|
fget_name(player->file, name, 16);
|
|
struct stream_file_info info = {
|
|
.file = player,
|
|
.fname = (char *)name,
|
|
.ops = &music_file_ops,
|
|
.scene = player->scene,
|
|
};
|
|
int err = jldemuxer_get_tone_file_fmt(&info, fmt);
|
|
|
|
return err;
|
|
}
|
|
|
|
const struct stream_file_ops music_file_ops = {
|
|
.read = music_file_read,
|
|
.seek = music_file_seek,
|
|
.close = music_file_close,
|
|
.get_fmt = music_file_get_fmt,
|
|
};
|
|
|
|
|
|
int music_file_player_pp(struct file_player *music_player)
|
|
{
|
|
if (music_player && music_player->stream) {
|
|
jlstream_pp_toggle(music_player->stream, 50);
|
|
if (music_player->status != FILE_PLAYER_STOP) {
|
|
music_player->status = ((music_player->status == FILE_PLAYER_START) ? FILE_PLAYER_PAUSE : FILE_PLAYER_START);
|
|
}
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int music_file_player_ff(u16 step_s, struct file_player *music_player)
|
|
{
|
|
if (music_player && music_player->stream) {
|
|
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_FF, step_s);
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int music_file_player_fr(u16 step_s, struct file_player *music_player)
|
|
{
|
|
if (music_player && music_player->stream) {
|
|
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_FR, step_s);
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int music_file_get_cur_time(struct file_player *music_player)
|
|
{
|
|
os_mutex_pend(&g_file_player.mutex, 0);
|
|
if (list_empty(&(g_file_player.head))) { //先判断是否为空
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return -1;
|
|
}
|
|
if (!music_player) {
|
|
music_player = list_first_entry(&(g_file_player.head), struct file_player, entry);
|
|
}
|
|
if (music_player && music_player->stream) {
|
|
int ret = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_GET_CUR_TIME, 0);
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return ret;
|
|
}
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return -1;
|
|
}
|
|
|
|
int music_file_get_total_time(struct file_player *music_player)
|
|
{
|
|
if (music_player && music_player->stream) {
|
|
return jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_GET_TOTAL_TIME, 0);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int music_file_get_player_status(struct file_player *music_player)
|
|
{
|
|
enum play_status status = FILE_PLAYER_STOP; //播放结束
|
|
if (!(list_empty(&(g_file_player.head))) && music_player && music_player->stream) {
|
|
return music_player->status;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
//变调接口
|
|
int music_file_pitch_up(struct file_player *music_player)
|
|
{
|
|
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
|
|
music_player->music_pitch_mode ++;
|
|
if (music_player->music_pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
|
|
music_player->music_pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
|
|
}
|
|
printf("play pitch up+++%d\n", music_player->music_pitch_mode);
|
|
int ret = music_file_set_pitch(music_player, music_player->music_pitch_mode);
|
|
ret = (ret == true) ? music_player->music_pitch_mode : -1;
|
|
return ret;
|
|
}
|
|
|
|
int music_file_pitch_down(struct file_player *music_player)
|
|
{
|
|
music_player->music_pitch_mode --;
|
|
if (music_player->music_pitch_mode < 0) {
|
|
music_player->music_pitch_mode = 0;
|
|
}
|
|
printf("play pitch down---%d\n", music_player->music_pitch_mode);
|
|
int ret = music_file_set_pitch(music_player, music_player->music_pitch_mode);
|
|
ret = (ret == true) ? music_player->music_pitch_mode : -1;
|
|
return ret;
|
|
}
|
|
|
|
int music_file_set_pitch(struct file_player *music_player, enum _pitch_level pitch_mode)
|
|
{
|
|
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
|
|
if (pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
|
|
pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
|
|
}
|
|
pitch_speed_param_tool_set pitch_param = {
|
|
.pitch = pitch_param_table[pitch_mode],
|
|
.speed = 1,
|
|
};
|
|
if (music_player) {
|
|
music_player->music_pitch_mode = pitch_mode;
|
|
return jlstream_node_ioctl(music_player->stream, NODE_UUID_PITCH_SPEED, NODE_IOC_SET_PARAM, (int)&pitch_param);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int music_file_speed_up(struct file_player *music_player) //倍速播放接口
|
|
{
|
|
float speed_param_table[] = {0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0};
|
|
music_player->music_speed_mode ++;
|
|
if (music_player->music_speed_mode > ARRAY_SIZE(speed_param_table) - 1) {
|
|
music_player->music_speed_mode = ARRAY_SIZE(speed_param_table) - 1;
|
|
}
|
|
|
|
printf("play speed up+++%d\n", music_player->music_speed_mode);
|
|
int ret = music_file_set_speed(music_player, music_player->music_speed_mode);
|
|
ret = (ret == true) ? music_player->music_speed_mode : -1;
|
|
return ret;
|
|
}
|
|
|
|
int music_file_speed_down(struct file_player *music_player) //慢速播放接口
|
|
{
|
|
music_player->music_speed_mode --;
|
|
if (music_player->music_speed_mode < 0) {
|
|
music_player->music_speed_mode = 0;
|
|
}
|
|
printf("play speed down---%d\n", music_player->music_speed_mode);
|
|
int ret = music_file_set_speed(music_player, music_player->music_speed_mode);
|
|
ret = (ret == true) ? music_player->music_speed_mode : -1;
|
|
return ret;
|
|
}
|
|
|
|
|
|
int music_file_set_speed(struct file_player *music_player, enum _speed_level speed_mode) //设置播放速度
|
|
{
|
|
float speed_param_table[] = {0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0};
|
|
|
|
if (speed_mode > ARRAY_SIZE(speed_param_table) - 1) {
|
|
speed_mode = ARRAY_SIZE(speed_param_table) - 1;
|
|
}
|
|
pitch_speed_param_tool_set speed_param = {
|
|
.pitch = 0,
|
|
.speed = speed_param_table[speed_mode],
|
|
};
|
|
if (music_player) {
|
|
printf("set play speed ---%d, %d\n", music_player->music_speed_mode, (int)(speed_param_table[music_player->music_speed_mode] * 100));
|
|
music_player->music_speed_mode = speed_mode;
|
|
return jlstream_node_ioctl(music_player->stream, NODE_UUID_PITCH_SPEED, NODE_IOC_SET_PARAM, (int)&speed_param);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#if FILE_DEC_AB_REPEAT_EN
|
|
#define AUDIO_AB_REPEAT_CODING_TYPE (AUDIO_CODING_MP3 | AUDIO_CODING_WMA | AUDIO_CODING_WAV | AUDIO_CODING_FLAC | AUDIO_CODING_APE | AUDIO_CODING_DTS)
|
|
enum {
|
|
AB_REPEAT_STA_NON = 0,
|
|
AB_REPEAT_STA_ASTA,
|
|
AB_REPEAT_STA_BSTA,
|
|
};
|
|
|
|
static u8 ab_repeat_status = AB_REPEAT_STA_NON; // AB复读状态
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 设置AB点复读命令
|
|
@param ab_cmd: 命令
|
|
@param ab_mode: 参数
|
|
@return 1: 设置成功 0:设置失败
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static int music_file_ab_repeat_set(int ab_cmd, int ab_mode, struct file_player *music_player)
|
|
{
|
|
int err = false;
|
|
if (!music_player) {
|
|
return false;
|
|
}
|
|
printf("ab repat, cmd:0x%x, mode:%d \n", ab_cmd, ab_mode);
|
|
struct audio_ab_repeat_mode_param rpt = {0};
|
|
rpt.value = ab_mode;
|
|
switch (ab_cmd) {
|
|
case AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A:
|
|
printf(" SET BREAKPOINT A");
|
|
err = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_SET_BP_A, (int)&rpt);
|
|
break;
|
|
case AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B:
|
|
printf(" SET BREAKPOINT B");
|
|
err = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_SET_BP_B, (int)&rpt);
|
|
break;
|
|
case AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE:
|
|
printf(" CANCEL AB REPEAT");
|
|
err = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_SET_AB_REPEAT, (int)&rpt);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 切换AB点复读状态
|
|
@param
|
|
@return true:成功
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
int music_file_ab_repeat_switch(struct file_player *music_player)
|
|
{
|
|
if (!music_player) {
|
|
return false;
|
|
}
|
|
switch (music_player->ab_repeat_status) {
|
|
case AB_REPEAT_STA_NON:
|
|
if (music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A, 0, music_player)) {
|
|
music_player->ab_repeat_status = AB_REPEAT_STA_ASTA;
|
|
}
|
|
break;
|
|
case AB_REPEAT_STA_ASTA:
|
|
if (music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, 0, music_player)) {
|
|
music_player->ab_repeat_status = AB_REPEAT_STA_BSTA;
|
|
}
|
|
break;
|
|
case AB_REPEAT_STA_BSTA:
|
|
if (music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, AB_REPEAT_MODE_CUR, music_player)) {
|
|
music_player->ab_repeat_status = AB_REPEAT_STA_NON;
|
|
}
|
|
break;
|
|
}
|
|
printf("music_file_ab_repeat_switch = %d\n", music_player->ab_repeat_status);
|
|
return true;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 关闭AB点复读
|
|
@param
|
|
@return true:成功
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
int music_file_ab_repeat_close(struct file_player *music_player)
|
|
{
|
|
if (!music_player) {
|
|
return false;
|
|
}
|
|
|
|
if (music_player->ab_repeat_status == AB_REPEAT_STA_NON) {
|
|
return true;
|
|
}
|
|
|
|
if (music_player->ab_repeat_status == AB_REPEAT_STA_ASTA) {
|
|
struct stream_fmt fmt;
|
|
jlstream_node_ioctl(music_player->stream, NODE_UUID_SOURCE, NODE_IOC_GET_FMT, (int)&fmt);
|
|
switch (fmt.coding_type) {
|
|
case AUDIO_CODING_FLAC:
|
|
case AUDIO_CODING_DTS:
|
|
case AUDIO_CODING_APE:
|
|
music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, 0, music_player);
|
|
break;
|
|
}
|
|
}
|
|
|
|
music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, AB_REPEAT_MODE_CUR, music_player);
|
|
music_player->ab_repeat_status = AB_REPEAT_STA_NON;
|
|
return true;
|
|
}
|
|
|
|
#endif /*FILE_DEC_AB_REPEAT_EN*/
|
|
|
|
|
|
int music_file_get_breakpoints(struct audio_dec_breakpoint *bp, struct file_player *music_player)
|
|
{
|
|
if (music_player) {
|
|
return jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_GET_BP, (int)bp);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#if FILE_DEC_REPEAT_EN //无缝循环播放
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 循环播放回调接口
|
|
@param *priv: 私有参数
|
|
@return 0:循环播放
|
|
@return 非0:结束循环
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static int file_dec_repeat_cb(void *priv)
|
|
{
|
|
struct file_player *music_player = priv;
|
|
y_printf("file_dec_repeat_cb\n");
|
|
if (music_player->repeat_num) {
|
|
music_player->repeat_num--;
|
|
} else {
|
|
printf("file_dec_repeat_cb end\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 设置循环播放次数
|
|
@param repeat_num: 循环次数
|
|
@return true:成功
|
|
@return false:失败
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
static struct audio_repeat_mode_param rep = {0};
|
|
int file_dec_repeat_set(u8 repeat_num, u32 coding_type)
|
|
{
|
|
struct file_player *music_player = g_file_player.cur_player; //当前的音乐播放器句柄
|
|
if (!music_player) {
|
|
return false;
|
|
}
|
|
|
|
switch (music_player->stream->coding_type) {
|
|
case AUDIO_CODING_MP3:
|
|
case AUDIO_CODING_WAV: {
|
|
music_player->repeat_num = repeat_num;
|
|
/* struct audio_repeat_mode_param rep = {0}; */
|
|
rep.flag = 1; //使能
|
|
rep.headcut_frame = 2; //依据需求砍掉前面几帧,仅mp3格式有效
|
|
rep.tailcut_frame = 2; //依据需求砍掉后面几帧,仅mp3格式有效
|
|
rep.repeat_callback = file_dec_repeat_cb;
|
|
rep.callback_priv = music_player;
|
|
rep.repair_buf = &music_player->repair_buf;
|
|
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_REPEAT, (int)&rep);
|
|
/* audio_decoder_ioctrl(&dec->file_dec.decoder, AUDIO_IOCTRL_CMD_REPEAT_PLAY, &rep); */
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if FILE_DEC_DEST_PLAY
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 跳到指定位置开始播放,播放到目标时间后回调
|
|
@param start_time: 要跳转过去播放的起始时间
|
|
@param dest_time: 要跳转过去播放的目标时间
|
|
@param *cb: 到达目标时间后回调
|
|
@param *cb_priv: 回调参数
|
|
@return true:成功
|
|
@return false:失败
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
struct audio_dest_time_play_param param = {0};
|
|
int file_dec_set_start_dest_play(u32 start_time, u32 dest_time, u32(*cb)(void *), void *cb_priv, u32 coding_type, struct file_player *music_player)
|
|
{
|
|
if (!music_player) {
|
|
return false;
|
|
}
|
|
switch (coding_type) {
|
|
case AUDIO_CODING_MP3: {
|
|
/* struct audio_dest_time_play_param param = {0}; */
|
|
param.start_time = start_time;
|
|
param.dest_time = dest_time;
|
|
param.callback_func = cb;
|
|
param.callback_priv = cb_priv;
|
|
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_DEST_PLAY, (int)¶m);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
/**@brief 跳到指定位置开始播放
|
|
@param start_time: 要跳转过去播放的起始时间
|
|
@return true:成功
|
|
@return false:失败
|
|
@note
|
|
*/
|
|
/*----------------------------------------------------------------------------*/
|
|
int file_dec_set_start_play(u32 start_time, u32 coding_type)
|
|
{
|
|
return file_dec_set_start_dest_play(start_time, 0x7fffffff, NULL, NULL, g_file_player.cur_player->stream->coding_type, g_file_player.cur_player);
|
|
}
|
|
#endif
|
|
|
|
|
|
static int music_file_player_start(struct file_player *player)
|
|
{
|
|
int err = -EINVAL;
|
|
|
|
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"music");
|
|
|
|
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_MUSIC);
|
|
if (!player->stream) {
|
|
goto __exit0;
|
|
}
|
|
|
|
#if TCFG_USER_EMITTER_ENABLE
|
|
extern u8 *get_cur_connect_emitter_mac_addr(void);
|
|
void *bt_addr = get_cur_connect_emitter_mac_addr();
|
|
if (!bt_addr) {
|
|
printf("========================= err bt_addr null");
|
|
} else {
|
|
jlstream_node_ioctl(player->stream, NODE_UUID_A2DP_TX, NODE_IOC_SET_BTADDR, (int)bt_addr);
|
|
}
|
|
|
|
#endif
|
|
|
|
int player_id = player->player_id;
|
|
jlstream_set_callback(player->stream, (void *)player_id, music_player_callback);
|
|
jlstream_set_scene(player->stream, player->scene);
|
|
jlstream_set_coexist(player->stream, player->coexist);
|
|
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
|
|
NODE_IOC_SET_BP, (int)player->break_point);
|
|
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
|
|
NODE_IOC_SET_FILE_LEN, (int)music_file_flen(player));
|
|
|
|
if (player->callback) {
|
|
err = player->callback(player->priv, 0, STREAM_EVENT_INIT);
|
|
if (err) {
|
|
goto __exit1;
|
|
}
|
|
}
|
|
|
|
jlstream_set_dec_file(player->stream, player, &music_file_ops);
|
|
|
|
err = jlstream_start(player->stream);
|
|
|
|
if (player->stream->coding_type == AUDIO_CODING_MP3) {
|
|
#if TCFG_DEC_ID3_V1_ENABLE
|
|
if (player->p_mp3_id3_v1) {
|
|
id3_obj_post(&player->p_mp3_id3_v1);
|
|
}
|
|
player->p_mp3_id3_v1 = id3_v1_obj_get(player->file);
|
|
#endif
|
|
#if TCFG_DEC_ID3_V2_ENABLE
|
|
if (player->p_mp3_id3_v2) {
|
|
id3_obj_post(&player->p_mp3_id3_v2);
|
|
}
|
|
player->p_mp3_id3_v2 = id3_v2_obj_get(player->file);
|
|
#endif
|
|
}
|
|
|
|
if (err) {
|
|
goto __exit1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
__exit1:
|
|
jlstream_release(player->stream);
|
|
__exit0:
|
|
list_del(&player->entry);
|
|
|
|
if (player->callback) {
|
|
/* err = player->callback(player->priv, 0,STREAM_EVENT_NONE); */
|
|
}
|
|
music_player_free(player);
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
|
|
int music_player_init(struct file_player *player, void *file, struct audio_dec_breakpoint *dbp)
|
|
{
|
|
player->ref = 1;
|
|
if (!file) {
|
|
printf("music_player_faild\n");
|
|
return -EINVAL;
|
|
}
|
|
player->file = file;
|
|
player->scene = STREAM_SCENE_MUSIC;
|
|
player->player_id = g_file_player.player_id++;
|
|
player->coexist = STREAM_COEXIST_AUTO;
|
|
|
|
if (dbp == NULL) {
|
|
player->break_point = zalloc(sizeof(struct audio_dec_breakpoint) + BREAKPOINT_DATA_LEN);
|
|
player->break_point->data_len = BREAKPOINT_DATA_LEN;
|
|
player->break_point_flag = 1;
|
|
} else {
|
|
player->break_point = dbp;
|
|
player->break_point_flag = 0;
|
|
}
|
|
player->music_speed_mode = PLAY_SPEED_1; //固定开始的时候使用1倍速播放 */
|
|
player->music_pitch_mode = PITCH_0; //固定开始时不变调
|
|
#if TCFG_DEC_DECRYPT_ENABLE
|
|
cipher_init(&player->mply_cipher, TCFG_DEC_DECRYPT_KEY);
|
|
void cipher_check_decode_file(CIPHER * pcipher, void *file);
|
|
cipher_check_decode_file(&player->mply_cipher, file);
|
|
#endif
|
|
|
|
|
|
INIT_LIST_HEAD(&player->entry);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct file_player *music_player_create(void *file, struct audio_dec_breakpoint *dbp)
|
|
{
|
|
struct file_player *player;
|
|
|
|
player = zalloc(sizeof(*player));
|
|
if (!player) {
|
|
return NULL;
|
|
}
|
|
|
|
#if FILE_DEC_DEST_PLAY || FILE_DEC_REPEAT_EN
|
|
g_file_player.cur_player = player;
|
|
#endif
|
|
|
|
int err = music_player_init(player, file, dbp);
|
|
if (err) {
|
|
music_player_free(player);
|
|
return NULL;
|
|
}
|
|
|
|
return player;
|
|
}
|
|
|
|
struct file_player *music_player_add(struct file_player *player)
|
|
{
|
|
os_mutex_pend(&g_file_player.mutex, 0);
|
|
if (list_empty(&(g_file_player.head))) {
|
|
int err = music_file_player_start(player);
|
|
if (err) {
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return NULL;
|
|
}
|
|
player->status = FILE_PLAYER_START;
|
|
}
|
|
list_add_tail(&player->entry, &(g_file_player.head));
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return player;
|
|
}
|
|
|
|
struct file_player *music_file_play(FILE *file, struct audio_dec_breakpoint *dbp)
|
|
{
|
|
struct file_player *player;
|
|
player = music_player_create(file, dbp);
|
|
if (!player) {
|
|
return NULL;
|
|
}
|
|
return music_player_add(player);
|
|
}
|
|
|
|
struct file_player *music_file_play_callback(FILE *file, void *priv, music_player_cb_t callback, struct audio_dec_breakpoint *dbp)
|
|
{
|
|
struct file_player *player;
|
|
player = music_player_create(file, dbp);
|
|
if (!player) {
|
|
return NULL;
|
|
}
|
|
player->priv = priv;
|
|
player->callback = callback;
|
|
return music_player_add(player);
|
|
}
|
|
|
|
int music_player_runing()
|
|
{
|
|
local_irq_disable();
|
|
int ret = list_empty(&(g_file_player.head)) ? 0 : 1;
|
|
local_irq_enable();
|
|
return ret;
|
|
}
|
|
|
|
void music_file_player_stop()
|
|
{
|
|
struct file_player *player, *n;
|
|
|
|
os_mutex_pend(&g_file_player.mutex, 0);
|
|
|
|
list_for_each_entry_safe(player, n, &(g_file_player.head), entry) {
|
|
__list_del_entry(&player->entry);
|
|
if (player->stream) {
|
|
jlstream_stop(player->stream, 50);
|
|
jlstream_release(player->stream);
|
|
}
|
|
#if TCFG_DEC_ID3_V1_ENABLE
|
|
if (player->p_mp3_id3_v1) {
|
|
id3_obj_post(&player->p_mp3_id3_v1);
|
|
}
|
|
#endif
|
|
#if TCFG_DEC_ID3_V2_ENABLE
|
|
if (player->p_mp3_id3_v2) {
|
|
id3_obj_post(&player->p_mp3_id3_v2);
|
|
}
|
|
#endif
|
|
|
|
music_player_free(player);
|
|
}
|
|
|
|
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"music");
|
|
os_mutex_post(&g_file_player.mutex);
|
|
}
|
|
|
|
struct file_player *get_music_file_player(void) //返回第一个打开的音乐播放器指针
|
|
{
|
|
struct file_player *player = NULL;
|
|
os_mutex_pend(&g_file_player.mutex, 0);
|
|
if (list_empty(&(g_file_player.head))) { //先判断是否为空
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return NULL;
|
|
}
|
|
player = list_first_entry(&(g_file_player.head), struct file_player, entry);
|
|
os_mutex_post(&g_file_player.mutex);
|
|
return player;
|
|
}
|
|
|
|
|
|
static int __music_player_init()
|
|
{
|
|
INIT_LIST_HEAD(&g_file_player.head);
|
|
os_mutex_create(&g_file_player.mutex);
|
|
return 0;
|
|
}
|
|
__initcall(__music_player_init);
|
|
|
|
#endif
|