初版
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
#ifndef A2DP_PLAYER_H
|
||||
#define A2DP_PLAYER_H
|
||||
|
||||
#include "effect/effects_default_param.h"
|
||||
|
||||
int a2dp_player_open(u8 *btaddr);
|
||||
|
||||
int a2dp_player_open_for_jl_dongle(u8 *btaddr, u16 latency_msec, u8 dynamic_latency_en);
|
||||
|
||||
void a2dp_player_close(u8 *btaddr);
|
||||
|
||||
int a2dp_player_get_btaddr(u8 *btaddr);
|
||||
|
||||
int a2dp_player_runing();
|
||||
|
||||
bool a2dp_player_is_playing(u8 *bt_addr);
|
||||
|
||||
int a2dp_player_start_slience_detect(u8 *btaddr, void (*handler)(u8 *, bool), int msec);
|
||||
|
||||
void a2dp_player_tws_event_handler(int *msg);
|
||||
|
||||
void a2dp_play_close(u8 *bt_addr);
|
||||
|
||||
void a2dp_player_low_latency_enable(u8 enable);
|
||||
|
||||
extern void a2dp_file_low_latency_enable(u8 enable);
|
||||
|
||||
int a2dp_file_pitch_up();
|
||||
|
||||
int a2dp_file_pitch_down();
|
||||
|
||||
int a2dp_file_set_pitch(enum _pitch_level pitch_mode);
|
||||
|
||||
void a2dp_file_pitch_mode_init(enum _pitch_level pitch_mode);
|
||||
|
||||
void a2dp_player_reset(void);
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef adda_loop_PLAYER_H
|
||||
#define adda_loop_PLAYER_H
|
||||
|
||||
#include "effect/effects_default_param.h"
|
||||
|
||||
int adda_loop_player_open();
|
||||
|
||||
void adda_loop_player_close();
|
||||
|
||||
bool adda_loop_player_runing();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
#ifndef _LE_AUDIO_PLAYER_H_
|
||||
#define _LE_AUDIO_PLAYER_H_
|
||||
|
||||
|
||||
enum AI_SERVICE {
|
||||
AI_SERVICE_MEDIA,
|
||||
AI_SERVICE_CALL_DOWNSTREAM,
|
||||
AI_SERVICE_CALL_UPSTREAM,
|
||||
AI_SERVICE_VOICE
|
||||
};
|
||||
|
||||
struct ai_rx_player_param {
|
||||
u8 type;
|
||||
u8 channel_mode;
|
||||
u16 frame_dms; //帧长时间,单位 deci-ms (ms/10)
|
||||
u32 coding_type;
|
||||
u32 sample_rate;
|
||||
u32 bit_rate;
|
||||
};
|
||||
|
||||
struct ai_rx_file_handle {
|
||||
void *file;
|
||||
void *bt_addr;
|
||||
u8 start;
|
||||
u8 source;
|
||||
u8 reference;
|
||||
struct stream_node *node;
|
||||
u32 play_latency; //us
|
||||
struct ai_rx_player_param param;
|
||||
const struct stream_file_ops *file_ops;
|
||||
};
|
||||
|
||||
struct ai_rx_cb {
|
||||
enum stream_node_state(*get_frame_event_cb)(struct ai_rx_file_handle *hdl, struct stream_frame **pframe); // 事件回调
|
||||
};
|
||||
|
||||
enum opus_dec_frame_len {
|
||||
FRAME_LEN_40 = 0,
|
||||
FRAME_LEN_80,
|
||||
FRAME_LEN_160,
|
||||
};
|
||||
int ai_rx_player_open(void *file, u8 source, struct ai_rx_player_param *param);
|
||||
|
||||
void ai_rx_player_close(u8 source);
|
||||
|
||||
bool ai_rx_player_runing(u8 source);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef AI_VOICE_RECODER_H
|
||||
#define AI_VOICE_RECODER_H
|
||||
|
||||
|
||||
|
||||
int ai_voice_recoder_open(u32 code_type, u8 ai_type);
|
||||
|
||||
void ai_voice_recoder_close();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _AVI_AUDIO_PLAYER_H_
|
||||
#define _AVI_AUDIO_PLAYER_H_
|
||||
|
||||
|
||||
enum AVI_SERVICE {
|
||||
AVI_SERVICE_MEDIA,
|
||||
AVI_SERVICE_CALL_DOWNSTREAM,
|
||||
AVI_SERVICE_CALL_UPSTREAM,
|
||||
AVI_SERVICE_VOICE
|
||||
};
|
||||
|
||||
struct avi_audio_player_param {
|
||||
u8 type;
|
||||
u8 channel_mode;
|
||||
u16 frame_dms; //帧长时间,单位 deci-ms (ms/10)
|
||||
u32 coding_type;
|
||||
u32 sample_rate;
|
||||
u32 bit_rate;
|
||||
};
|
||||
|
||||
enum avi_dec_frame_len {
|
||||
FRAME_LEN_40 = 0,
|
||||
FRAME_LEN_80,
|
||||
FRAME_LEN_160,
|
||||
};
|
||||
|
||||
int avi_audio_player_open(void *file, u8 source, struct avi_audio_player_param *param);
|
||||
|
||||
void avi_audio_player_close(u8 source);
|
||||
|
||||
bool avi_audio_player_runing(u8 source);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef CVP_NODE_H
|
||||
#define CVP_NODE_H
|
||||
|
||||
#include "audio_config.h"
|
||||
#include "audio_cvp.h"
|
||||
#include "effects/effects_adj.h"
|
||||
#include "adc_file.h"
|
||||
|
||||
int cvp_node_param_cfg_read(void *priv, u8 ignore_subid);
|
||||
int cvp_node_output_handle(s16 *data, u16 len);
|
||||
|
||||
int cvp_param_cfg_read(void);
|
||||
u8 cvp_get_talk_mic_ch(void);
|
||||
u8 cvp_get_talk_ref_mic_ch(void);
|
||||
u8 cvp_get_talk_fb_mic_ch(void);
|
||||
|
||||
#endif/*CVP_NODE_H*/
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef DEV_FLOW_PLAYER_H
|
||||
#define DEV_FLOW_PLAYER_H
|
||||
|
||||
|
||||
|
||||
int dev_flow_player_open();
|
||||
|
||||
void dev_flow_player_close();
|
||||
|
||||
bool dev_flow_player_runing();
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef DEV_FLOW_RECODER_H
|
||||
#define DEV_FLOW_RECODER_H
|
||||
|
||||
|
||||
int dev_flow_recoder_open(void);
|
||||
|
||||
void dev_flow_recoder_close(void);
|
||||
|
||||
bool dev_flow_recoder_runing(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ESCO_PLAYER_H
|
||||
#define ESCO_PLAYER_H
|
||||
|
||||
|
||||
|
||||
int esco_player_open(u8 *bt_addr);
|
||||
|
||||
void esco_player_close();
|
||||
|
||||
bool esco_player_runing();
|
||||
|
||||
int esco_player_get_btaddr(u8 *btaddr);
|
||||
|
||||
int esco_player_is_playing(u8 *btaddr);
|
||||
int esco_player_start(u8 *bt_addr);
|
||||
int esco_player_suspend(u8 *bt_addr);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef ESCO_RECODER_H
|
||||
#define ESCO_RECODER_H
|
||||
|
||||
|
||||
#define COMMON_SCO 0 //普通SCO
|
||||
#define JL_DOGLE_ACL 1 //dongle ACL链路
|
||||
|
||||
|
||||
|
||||
int esco_recoder_open(u8 link_type, void *bt_addr);
|
||||
|
||||
void esco_recoder_close();
|
||||
|
||||
int esco_recoder_switch(u8 en);
|
||||
|
||||
int esco_recoder_reset(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
#ifndef MUSIC_PLAYER_H
|
||||
#define MUSIC_PLAYER_H
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "jlstream.h"
|
||||
#include "music/music_decrypt.h"
|
||||
#include "music/music_id3.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_decoder.h"
|
||||
#include "fs/fs.h"
|
||||
#include "effect/effects_default_param.h"
|
||||
|
||||
#define MAX_FILE_NUM 20
|
||||
|
||||
#if (defined(TCFG_DEC_APE_ENABLE) && (TCFG_DEC_APE_ENABLE))
|
||||
#define BREAKPOINT_DATA_LEN (2036 + 4)
|
||||
#elif (defined(TCFG_DEC_FLAC_ENABLE) && (TCFG_DEC_FLAC_ENABLE))
|
||||
#define BREAKPOINT_DATA_LEN 688
|
||||
#elif (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE)
|
||||
#define BREAKPOINT_DATA_LEN 536
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_BR18
|
||||
#ifndef BREAKPOINT_DATA_LEN
|
||||
#define BREAKPOINT_DATA_LEN 80
|
||||
#endif
|
||||
#else
|
||||
#ifndef BREAKPOINT_DATA_LEN
|
||||
#define BREAKPOINT_DATA_LEN 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef int (*music_player_cb_t)(void *, int parm, enum stream_event);
|
||||
|
||||
enum play_status {
|
||||
FILE_PLAYER_STOP = 0x0, //播放结束
|
||||
FILE_PLAYER_START, //播放中
|
||||
FILE_PLAYER_PAUSE//播放暂停
|
||||
};
|
||||
|
||||
struct file_player {
|
||||
struct list_head entry;
|
||||
u8 ref;
|
||||
u8 index;
|
||||
u8 player_id;
|
||||
enum stream_scene scene;
|
||||
enum stream_coexist coexist;
|
||||
u32 coding_type;
|
||||
|
||||
struct jlstream *stream;
|
||||
|
||||
void *file;
|
||||
const char *file_name_list[MAX_FILE_NUM + 1];
|
||||
|
||||
void *priv;
|
||||
music_player_cb_t callback;
|
||||
|
||||
CIPHER mply_cipher; // 解密播放
|
||||
|
||||
#if TCFG_DEC_ID3_V1_ENABLE
|
||||
MP3_ID3_OBJ *p_mp3_id3_v1; // id3_v1信息
|
||||
#endif
|
||||
#if TCFG_DEC_ID3_V2_ENABLE
|
||||
MP3_ID3_OBJ *p_mp3_id3_v2; // id3_v2信息
|
||||
#endif
|
||||
|
||||
#if FILE_DEC_REPEAT_EN
|
||||
u8 repeat_num; // 无缝循环次数
|
||||
struct fixphase_repair_obj repair_buf; // 无缝循环句柄
|
||||
#endif
|
||||
struct audio_dec_breakpoint *break_point;
|
||||
u8 read_err;
|
||||
u8 ab_repeat_status;
|
||||
s8 music_speed_mode; //播放倍速
|
||||
s8 music_pitch_mode; //变调模式
|
||||
enum play_status status; //播放状态
|
||||
u8 break_point_flag; //是否有播放器申请的断点
|
||||
};
|
||||
|
||||
// AB点复读模式
|
||||
enum {
|
||||
AB_REPEAT_MODE_BP_A = 0x01,
|
||||
AB_REPEAT_MODE_BP_B,
|
||||
AB_REPEAT_MODE_CUR,
|
||||
};
|
||||
|
||||
enum _speed_level {
|
||||
PLAY_SPEED_0_5 = 0x0, //0.5倍速
|
||||
PLAY_SPEED_0_75, //0.75倍速
|
||||
PLAY_SPEED_1, // 1倍速
|
||||
PLAY_SPEED_1_25, //1.25倍速
|
||||
PLAY_SPEED_1_5, //1.5倍速
|
||||
PLAY_SPEED_2, // 2倍速
|
||||
PLAY_SPEED_3, // 3倍速
|
||||
PLAY_SPEED_4, // 4倍速
|
||||
};
|
||||
|
||||
int music_player_init(struct file_player *player, void *file, struct audio_dec_breakpoint *dbp);
|
||||
/* ---------------------音乐播放API-----------------------------
|
||||
*
|
||||
* 音乐和其它音频之间默认采用叠加方式播放,可能由于资源限制而采用打断的方式播放
|
||||
* 音乐和音乐之间默认不抢占,采用排队方式播放
|
||||
*
|
||||
* ---------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 播放单个音乐文件
|
||||
*/
|
||||
struct file_player *music_file_play(FILE *file, struct audio_dec_breakpoint *dbp);
|
||||
|
||||
/*
|
||||
* 播放单个音乐文件,带有播放状态回调参数
|
||||
*/
|
||||
struct file_player *music_file_play_callback(FILE *file, void *priv,
|
||||
music_player_cb_t callback,
|
||||
struct audio_dec_breakpoint *dbp
|
||||
);
|
||||
/*
|
||||
* 停止播放所有音乐
|
||||
*/
|
||||
void music_file_player_stop();
|
||||
/*
|
||||
* 返回是否有音乐在播放
|
||||
*/
|
||||
int music_player_runing();
|
||||
|
||||
//返回第一个打开的音乐播放器指针
|
||||
struct file_player *get_music_file_player(void);
|
||||
int music_file_player_pp(struct file_player *music_player);
|
||||
int music_file_player_ff(u16 step_s, struct file_player *music_player);
|
||||
int music_file_player_fr(u16 step_s, struct file_player *music_player);
|
||||
int music_file_ab_repeat_switch(struct file_player *music_player);
|
||||
|
||||
int music_file_pitch_up(struct file_player *music_player);
|
||||
int music_file_pitch_down(struct file_player *music_player);
|
||||
int music_file_set_pitch(struct file_player *music_player, enum _pitch_level pitch_mode);
|
||||
/*
|
||||
* 加速音乐播放,设置成功返回当前倍速播放的speed值,失败则返回-1
|
||||
*/
|
||||
int music_file_speed_up(struct file_player *music_player); //倍速播放接口
|
||||
/*
|
||||
* 减速音乐播放,设置成功返回当前倍速播放的speed值,失败则返回-1
|
||||
*/
|
||||
int music_file_speed_down(struct file_player *music_player); //慢速播放接口
|
||||
|
||||
|
||||
int music_file_get_breakpoints(struct audio_dec_breakpoint *bp, struct file_player *music_player);
|
||||
|
||||
|
||||
int music_file_set_speed(struct file_player *music_player, enum _speed_level speed_mode); //设置播放速度
|
||||
|
||||
int music_file_get_player_status(struct file_player *music_player);
|
||||
|
||||
int music_file_get_cur_time(struct file_player *music_player);
|
||||
|
||||
int music_file_get_total_time(struct file_player *music_player);
|
||||
|
||||
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);
|
||||
int file_dec_set_start_play(u32 start_time, u32 coding_type);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef _FILE_RECODER_H_
|
||||
#define _FILE_RECODER_H_
|
||||
|
||||
#include "jlstream.h"
|
||||
#include "encoder_node.h"
|
||||
#include "fs/fs.h"
|
||||
|
||||
#define AUDIO_RECORD_CUT_HEAD_TAIL_EN 1
|
||||
#define RECODER_DEVICE_LOGO "sd0"
|
||||
|
||||
typedef void (*file_recorder_cb_t)(void *, enum stream_state);
|
||||
|
||||
struct file_recorder {
|
||||
struct list_head entry;
|
||||
void *file;
|
||||
void *priv;
|
||||
file_recorder_cb_t callback;
|
||||
const struct stream_file_ops *fops;
|
||||
struct jlstream *stream;
|
||||
#if AUDIO_RECORD_CUT_HEAD_TAIL_EN
|
||||
u8 head_size;
|
||||
u16 cut_head_timer;
|
||||
u32 cut_tail_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct file_recorder *file_recorder_open(int pipeline_uuid, int snode_uuid);
|
||||
|
||||
int file_recorder_get_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt);
|
||||
|
||||
int file_recorder_set_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt);
|
||||
|
||||
FILE *file_recorder_open_file(struct file_recorder *recorder, const char *fname);
|
||||
|
||||
int file_recorder_set_file(struct file_recorder *recorder, void *file,
|
||||
const struct stream_file_ops *fops);
|
||||
|
||||
void *file_recorder_change_file(struct file_recorder *recorder, void *new_file);
|
||||
|
||||
void file_recorder_set_callback(struct file_recorder *recorder, void *priv,
|
||||
file_recorder_cb_t callback);
|
||||
|
||||
|
||||
void file_recorder_seamless_set(struct file_recorder *recorder, struct seamless_recording *seamless);
|
||||
|
||||
int file_recorder_start(struct file_recorder *recorder);
|
||||
|
||||
int file_recorder_close(struct file_recorder *recorder, bool close_file);
|
||||
|
||||
int file_recorder_get_enc_time(struct file_recorder *recorder);
|
||||
|
||||
int file_recorder_stop(struct file_recorder *recorder, bool close_file);
|
||||
|
||||
int file_recorder_release(struct file_recorder *recorder);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef FM_PLAYER_H
|
||||
#define FM_PLAYER_H
|
||||
|
||||
#include "effect/effects_default_param.h"
|
||||
|
||||
int fm_player_open();
|
||||
|
||||
void fm_player_close();
|
||||
|
||||
bool fm_player_runing();
|
||||
|
||||
int fm_file_pitch_up();
|
||||
|
||||
int fm_file_pitch_down();
|
||||
|
||||
int fm_file_set_pitch(enum _pitch_level pitch_mode);
|
||||
|
||||
void fm_file_pitch_mode_init(enum _pitch_level pitch_mode);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef LINEIN_PLAYER_H
|
||||
#define LINEIN_PLAYER_H
|
||||
|
||||
#include "effect/effects_default_param.h"
|
||||
|
||||
int linein_player_open();
|
||||
|
||||
void linein_player_close();
|
||||
|
||||
bool linein_player_runing();
|
||||
|
||||
int linein_player_playing();
|
||||
|
||||
int linein_file_pitch_up();
|
||||
|
||||
int linein_file_pitch_down();
|
||||
|
||||
int linein_file_set_pitch(enum _pitch_level pitch_mode);
|
||||
|
||||
void linein_file_pitch_mode_init(enum _pitch_level pitch_mode);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef __PC_MIC_RECODER
|
||||
#define __PC_MIC_RECODER
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
int pc_mic_recoder_open(void);
|
||||
void pc_mic_recoder_close(void);
|
||||
int pc_mic_recoder_open_by_taskq(void);
|
||||
int pc_mic_recoder_close_by_taskq(void);
|
||||
int pc_mic_recoder_restart_by_taskq(void);
|
||||
int pc_mic_set_volume_by_taskq(u32 mic_vol);
|
||||
extern u8 pc_mic_get_node_state(void);
|
||||
extern void pc_mic_set_fmt(u8 channel, u8 bit, u32 sample_rate);
|
||||
extern u32 pc_mic_get_fmt_sample_rate(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef __PC_RX_PLAYER_H
|
||||
#define __PC_RX_PLAYER_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
int pc_spk_player_open(void);
|
||||
void pc_spk_player_close(void);
|
||||
int pcspk_close_player_by_taskq(void);
|
||||
int pcspk_open_player_by_taskq(void);
|
||||
int pcspk_restart_player_by_taskq(void);
|
||||
int pcspk_set_volume_by_taskq(void);
|
||||
bool pc_spk_player_runing();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file reference_time.h
|
||||
*
|
||||
* \brief 音频的参考时钟选择与设置
|
||||
*
|
||||
* Copyright (c) 2011-2022 ZhuHai Jieli Technology Co.,Ltd.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef _REFERENCE_TIME_H_
|
||||
#define _REFERENCE_TIME_H_
|
||||
#include "typedef.h"
|
||||
|
||||
int audio_reference_clock_select(void *addr, u8 network);
|
||||
|
||||
u32 audio_reference_clock_time(void);
|
||||
|
||||
u32 audio_reference_network_clock_time(u8 network);
|
||||
|
||||
u8 is_audio_reference_clock_enable(void);
|
||||
|
||||
u8 audio_reference_clock_match(void *addr, u8 network);
|
||||
|
||||
u8 audio_reference_clock_network(void *addr);
|
||||
|
||||
void audio_reference_clock_exit(u8 id);
|
||||
|
||||
u32 audio_reference_clock_remapping(u8 now_network, u8 dst_network, u32 clock);
|
||||
|
||||
u8 audio_reference_network_exist(u8 reference);
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef __RING_PLAYER_H
|
||||
#define __RING_PLAYER_H
|
||||
|
||||
|
||||
int play_ring_file(const char *file_name);
|
||||
|
||||
int play_ring_file_alone(const char *file_name);
|
||||
|
||||
int play_ring_file_with_callback(const char *file_name, void *priv, tone_player_cb_t callback);
|
||||
|
||||
int play_ring_file_alone_with_callback(const char *file_name, void *priv, tone_player_cb_t callback);
|
||||
|
||||
bool ring_player_runing();
|
||||
|
||||
void ring_player_stop();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef TONE_PLAYER_H
|
||||
#define TONE_PLAYER_H
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "jlstream.h"
|
||||
|
||||
#define MAX_FILE_NUM 20
|
||||
|
||||
|
||||
typedef int (*tone_player_cb_t)(void *, enum stream_event);
|
||||
|
||||
struct tone_player {
|
||||
struct list_head entry;
|
||||
u8 ref;
|
||||
u8 index;
|
||||
u8 player_id;
|
||||
u8 channel_mode;
|
||||
enum stream_scene scene;
|
||||
enum stream_coexist coexist;
|
||||
u16 fname_uuid;
|
||||
u32 coding_type;
|
||||
u32 sample_rate;
|
||||
|
||||
struct jlstream *stream;
|
||||
|
||||
void *file;
|
||||
void *next_file;
|
||||
const char *file_name_list[MAX_FILE_NUM + 1];
|
||||
|
||||
void *priv;
|
||||
tone_player_cb_t callback;
|
||||
};
|
||||
|
||||
|
||||
int tone_player_init(struct tone_player *player, const char *file_name);
|
||||
|
||||
int tone_player_add(struct tone_player *player);
|
||||
|
||||
void tone_player_free(struct tone_player *player);
|
||||
|
||||
|
||||
|
||||
/* ---------------------提示音播放API-----------------------------
|
||||
*
|
||||
* 提示音和其它音频之间默认采用叠加方式播放,可能由于资源限制而采用打断的方式播放
|
||||
* 提示音和提示音之间默认不抢占,采用排队方式播放
|
||||
*
|
||||
* ---------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 播放单个提示音文件
|
||||
*/
|
||||
int play_tone_file(const char *file_name);
|
||||
|
||||
|
||||
/*
|
||||
* 播放单个提示音文件,带有播放状态回调参数
|
||||
*/
|
||||
int play_tone_file_callback(const char *file_name, void *priv,
|
||||
tone_player_cb_t callback);
|
||||
|
||||
/*
|
||||
* 打断方式播放单个提示音文件
|
||||
*/
|
||||
int play_tone_file_alone(const char *file_name);
|
||||
|
||||
|
||||
int play_tone_file_alone_callback(const char *file_name, void *priv,
|
||||
tone_player_cb_t callback);
|
||||
|
||||
|
||||
/*
|
||||
* 播放文件列表,内部不会复制文件名,file_name[x]指向的文件名地址要求播放过程中有效
|
||||
*/
|
||||
int play_tone_files(const char *const file_name[], u8 file_num);
|
||||
|
||||
int play_tone_files_alone(const char *const file_name[], u8 file_num);
|
||||
|
||||
int play_tone_files_callback(const char *const file_name[], u8 file_num,
|
||||
void *priv, tone_player_cb_t callback);
|
||||
|
||||
int play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
|
||||
void *priv, tone_player_cb_t callback);
|
||||
/*
|
||||
* 停止播放所有提示音
|
||||
*/
|
||||
void tone_player_stop();
|
||||
|
||||
/*
|
||||
* 返回是否有提示音在播放
|
||||
*/
|
||||
int tone_player_runing();
|
||||
|
||||
|
||||
/*
|
||||
* 播放按键音
|
||||
*/
|
||||
int play_key_tone_file(const char *file_name);
|
||||
|
||||
|
||||
/*
|
||||
* 提示音文件名转uuid, 全局的提示音播放结束事件中会有次参数,可用于识别是哪一个提示音
|
||||
*/
|
||||
u16 tone_player_get_fname_uuid(const char *fname);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef TWS_TONE_PLAYER_H
|
||||
#define TWS_TONE_PLAYER_H
|
||||
|
||||
#include "tone_player.h"
|
||||
#include "ring_player.h"
|
||||
|
||||
|
||||
typedef void (*tws_tone_cb_func_t)(int priv, enum stream_event event);
|
||||
|
||||
struct tws_tone_callback {
|
||||
int func_uuid;
|
||||
tws_tone_cb_func_t callback;
|
||||
const char *task_name;
|
||||
};
|
||||
|
||||
extern const struct tws_tone_callback tws_tone_cb_begin[];
|
||||
extern const struct tws_tone_callback tws_tone_cb_end[];
|
||||
|
||||
/*
|
||||
* 注册TWS回调函数, 播放结束时主从都会调用
|
||||
*/
|
||||
#define REGISTER_TWS_TONE_CALLBACK(cb_stub) \
|
||||
static const struct tws_tone_callback __tws_tone_##cb_stub sec(.tws_tone_callback)
|
||||
|
||||
|
||||
|
||||
/*---------------TWS同步播放提示音接口-----------------------
|
||||
*
|
||||
* delay_msec: 表示多少msec以后tws同时开始出声音
|
||||
* 由于TWS每次通信有一定的时间间隔,环境无线干扰可能导致通信失败
|
||||
* 建议delay_msec设置在300ms以上,以增加抗干扰的能力
|
||||
*
|
||||
* ---------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 默认叠加方式同步播放单个文件, 可能由于受资源限制而采样打断的方式播放
|
||||
*/
|
||||
int tws_play_tone_file(const char *file_name, int delay_msec);
|
||||
|
||||
int tws_play_tone_file_callback(const char *file_name, int delay_msec, u32 func_uuid);
|
||||
|
||||
|
||||
/*
|
||||
* 打断方式同步播放单个文件
|
||||
*/
|
||||
int tws_play_tone_file_alone(const char *file_name, int delay_msec);
|
||||
|
||||
int tws_play_tone_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid);
|
||||
|
||||
/*
|
||||
* 同步播放文件列表
|
||||
*/
|
||||
int tws_play_tone_files(const char *const file_name[], u8 file_num, int delay_msec);
|
||||
|
||||
int tws_play_tone_files_callback(const char *const file_name[], u8 file_num,
|
||||
int delay_msec, u32 func_uuid);
|
||||
|
||||
int tws_play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
|
||||
int delay_msec, u32 func_uuid);
|
||||
/*
|
||||
* 同步播放铃声
|
||||
*/
|
||||
int tws_play_ring_file(const char *file_name, int delay_msec);
|
||||
|
||||
int tws_play_ring_file_callback(const char *file_name, int delay_msec, u32 func_uuid);
|
||||
|
||||
int tws_play_ring_file_alone(const char *file_name, int delay_msec);
|
||||
|
||||
int tws_play_ring_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".a2dp_player.data.bss")
|
||||
#pragma data_seg(".a2dp_player.data")
|
||||
#pragma const_seg(".a2dp_player.text.const")
|
||||
#pragma code_seg(".a2dp_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "classic/tws_api.h"
|
||||
#include "media/audio_base.h"
|
||||
#include "a2dp_player.h"
|
||||
#include "btstack/a2dp_media_codec.h"
|
||||
#include "media/bt_audio_timestamp.h"
|
||||
#include "effects/audio_pitchspeed.h"
|
||||
#include "app_config.h"
|
||||
#include "effects/audio_vbass.h"
|
||||
#include "audio_config_def.h"
|
||||
|
||||
#if TCFG_AUDIO_DUT_ENABLE
|
||||
#include "audio_dut_control.h"
|
||||
#endif/*TCFG_AUDIO_DUT_ENABLE*/
|
||||
|
||||
#if (defined TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE) && TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE
|
||||
#include "icsd_adt_app.h"
|
||||
#endif
|
||||
|
||||
#if TCFG_SMART_VOICE_ENABLE
|
||||
#include "smart_voice/smart_voice.h"
|
||||
#endif
|
||||
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
struct a2dp_player {
|
||||
u8 bt_addr[6];
|
||||
u16 retry_timer;
|
||||
s8 a2dp_pitch_mode;
|
||||
struct jlstream *stream;
|
||||
};
|
||||
|
||||
extern void dac_try_power_on_task_delete();
|
||||
static struct a2dp_player *g_a2dp_player = NULL;
|
||||
extern const int CONFIG_BTCTLER_TWS_ENABLE;
|
||||
|
||||
|
||||
static void a2dp_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
|
||||
printf("a2dp_callback: %d\n", event);
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
#if AUDIO_VBASS_LINK_VOLUME
|
||||
vbass_link_volume();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void a2dp_player_set_audio_channel(struct a2dp_player *player)
|
||||
{
|
||||
int channel = AUDIO_CH_MIX;
|
||||
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
|
||||
channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
|
||||
}
|
||||
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, channel);
|
||||
}
|
||||
|
||||
void a2dp_player_tws_event_handler(int *msg)
|
||||
{
|
||||
struct tws_event *evt = (struct tws_event *)msg;
|
||||
u8 state = evt->args[1];
|
||||
|
||||
switch (evt->event) {
|
||||
case TWS_EVENT_MONITOR_START:
|
||||
if (!(state & TWS_STA_SBC_OPEN)) {
|
||||
break;
|
||||
}
|
||||
case TWS_EVENT_CONNECTION_DETACH:
|
||||
case TWS_EVENT_REMOVE_PAIRS:
|
||||
if (g_a2dp_player) {
|
||||
a2dp_player_set_audio_channel(g_a2dp_player);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
a2dp_tws_timestamp_event_handler(evt->event, evt->args);
|
||||
}
|
||||
|
||||
static int a2dp_player_create(u8 *btaddr)
|
||||
{
|
||||
int uuid;
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"a2dp");
|
||||
|
||||
if (player) {
|
||||
if (player->stream) {
|
||||
if (!memcmp(player->bt_addr, btaddr, 6)) {
|
||||
return -EEXIST;
|
||||
}
|
||||
puts("a2dp_player_busy\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (player->retry_timer) {
|
||||
sys_timer_del(player->retry_timer);
|
||||
player->retry_timer = 0;
|
||||
}
|
||||
} else {
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
g_a2dp_player = player;
|
||||
}
|
||||
|
||||
memcpy(player->bt_addr, btaddr, 6);
|
||||
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_A2DP_RX);
|
||||
if (!player->stream) {
|
||||
printf("create a2dp stream faild\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void a2dp_player_low_latency_enable(u8 enable)
|
||||
{
|
||||
#if TCFG_USER_BT_CLASSIC_ENABLE
|
||||
a2dp_file_low_latency_enable(enable);
|
||||
#endif /* #if TCFG_USER_BT_CLASSIC_ENABLE */
|
||||
}
|
||||
|
||||
static void retry_open_a2dp_player(void *p)
|
||||
{
|
||||
if (g_a2dp_player && !g_a2dp_player->stream) {
|
||||
a2dp_player_open(g_a2dp_player->bt_addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void retry_start_a2dp_player(void *p)
|
||||
{
|
||||
if (g_a2dp_player && g_a2dp_player->stream) {
|
||||
int err = jlstream_start(g_a2dp_player->stream);
|
||||
if (err == 0) {
|
||||
dac_try_power_on_task_delete();
|
||||
sys_timer_del(g_a2dp_player->retry_timer);
|
||||
g_a2dp_player->retry_timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int a2dp_player_open(u8 *btaddr)
|
||||
{
|
||||
int err;
|
||||
|
||||
#if (defined TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE) && TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE
|
||||
if (get_speak_to_chat_state() == AUDIO_ADT_CHAT) {
|
||||
audio_speak_to_char_sync_suspend();
|
||||
}
|
||||
#endif
|
||||
err = a2dp_player_create(btaddr);
|
||||
if (err) {
|
||||
if (err == -EFAULT) {
|
||||
g_a2dp_player->retry_timer = sys_timer_add(NULL, retry_open_a2dp_player, 200);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
|
||||
player->a2dp_pitch_mode = PITCH_0; //默认打开是原声调
|
||||
|
||||
jlstream_set_callback(player->stream, NULL, a2dp_player_callback);
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_A2DP);
|
||||
|
||||
if (CONFIG_BTCTLER_TWS_ENABLE) {
|
||||
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
|
||||
int channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, channel);
|
||||
}
|
||||
}
|
||||
err = jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE,
|
||||
NODE_IOC_SET_BTADDR, (int)player->bt_addr);
|
||||
if (err == 0) {
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
g_a2dp_player->retry_timer = sys_timer_add(NULL, retry_start_a2dp_player, 200);
|
||||
return 0;
|
||||
} else {
|
||||
dac_try_power_on_task_delete();
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
jlstream_release(player->stream);
|
||||
free(player);
|
||||
g_a2dp_player = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
#if (TCFG_SMART_VOICE_ENABLE && TCFG_SMART_VOICE_USE_AEC)
|
||||
audio_smart_voice_aec_open();
|
||||
#endif
|
||||
|
||||
puts("a2dp_open_dec_file_suss\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int a2dp_player_runing()
|
||||
{
|
||||
return g_a2dp_player ? 1 : 0;
|
||||
}
|
||||
|
||||
int a2dp_player_get_btaddr(u8 *btaddr)
|
||||
{
|
||||
if (g_a2dp_player) {
|
||||
memcpy(btaddr, g_a2dp_player->bt_addr, 6);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool a2dp_player_is_playing(u8 *bt_addr)
|
||||
{
|
||||
if (g_a2dp_player && memcmp(bt_addr, g_a2dp_player->bt_addr, 6) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int a2dp_player_start_slience_detect(u8 *btaddr, void (*handler)(u8 *, bool), int msec)
|
||||
{
|
||||
if (!g_a2dp_player || memcmp(g_a2dp_player->bt_addr, btaddr, 6)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void a2dp_player_close(u8 *btaddr)
|
||||
{
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
if (memcmp(player->bt_addr, btaddr, 6)) {
|
||||
return;
|
||||
}
|
||||
if (player->retry_timer) {
|
||||
sys_timer_del(player->retry_timer);
|
||||
player->retry_timer = 0;
|
||||
}
|
||||
if (player->stream) {
|
||||
jlstream_stop(player->stream, 100);
|
||||
jlstream_release(player->stream);
|
||||
}
|
||||
free(player);
|
||||
g_a2dp_player = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"a2dp");
|
||||
|
||||
#if (TCFG_SMART_VOICE_ENABLE && TCFG_SMART_VOICE_USE_AEC)
|
||||
audio_smart_voice_aec_close();
|
||||
#endif
|
||||
}
|
||||
|
||||
//复位当前的数据流
|
||||
void a2dp_player_reset(void)
|
||||
{
|
||||
u8 bt_addr[6];
|
||||
if (g_a2dp_player) {
|
||||
memcpy(bt_addr, g_a2dp_player->bt_addr, 6);
|
||||
a2dp_player_close(bt_addr);
|
||||
a2dp_player_open(bt_addr);
|
||||
}
|
||||
}
|
||||
|
||||
//变调接口
|
||||
int a2dp_file_pitch_up()
|
||||
{
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
if (!player) {
|
||||
return -1;
|
||||
}
|
||||
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
|
||||
player->a2dp_pitch_mode++;
|
||||
if (player->a2dp_pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
|
||||
player->a2dp_pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
|
||||
}
|
||||
printf("play pitch up+++%d\n", player->a2dp_pitch_mode);
|
||||
int ret = a2dp_file_set_pitch(player->a2dp_pitch_mode);
|
||||
ret = (ret == true) ? player->a2dp_pitch_mode : -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int a2dp_file_pitch_down()
|
||||
{
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
if (!player) {
|
||||
return -1;
|
||||
}
|
||||
player->a2dp_pitch_mode--;
|
||||
if (player->a2dp_pitch_mode < 0) {
|
||||
player->a2dp_pitch_mode = 0;
|
||||
}
|
||||
printf("play pitch down---%d\n", player->a2dp_pitch_mode);
|
||||
int ret = a2dp_file_set_pitch(player->a2dp_pitch_mode);
|
||||
ret = (ret == true) ? player->a2dp_pitch_mode : -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int a2dp_file_set_pitch(enum _pitch_level pitch_mode)
|
||||
{
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
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 (player) {
|
||||
player->a2dp_pitch_mode = pitch_mode;
|
||||
return jlstream_node_ioctl(player->stream, NODE_UUID_PITCH_SPEED, NODE_IOC_SET_PARAM, (int)&pitch_param);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void a2dp_file_pitch_mode_init(enum _pitch_level pitch_mode)
|
||||
{
|
||||
struct a2dp_player *player = g_a2dp_player;
|
||||
if (player) {
|
||||
player->a2dp_pitch_mode = pitch_mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".adda_loop_player.data.bss")
|
||||
#pragma data_seg(".adda_loop_player.data")
|
||||
#pragma const_seg(".adda_loop_player.text.const")
|
||||
#pragma code_seg(".adda_loop_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "adda_loop_player.h"
|
||||
#include "app_config.h"
|
||||
#include "effects/audio_pitchspeed.h"
|
||||
#include "audio_config_def.h"
|
||||
#include "effects/audio_vbass.h"
|
||||
#include "adc_file.h"
|
||||
#include "effects/effects_adj.h"
|
||||
struct adda_loop_player {
|
||||
struct jlstream *stream;
|
||||
int channel;
|
||||
};
|
||||
|
||||
static struct adda_loop_player *g_adda_loop_player = NULL;
|
||||
|
||||
static void adda_loop_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct adda_loop_player *player = g_adda_loop_player;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int adda_loop_dut_switch_channel(void)
|
||||
{
|
||||
if (g_adda_loop_player) {
|
||||
g_adda_loop_player->channel = (g_adda_loop_player->channel == AUDIO_CH_L ? AUDIO_CH_R : AUDIO_CH_L);
|
||||
int err = jlstream_ioctl(g_adda_loop_player->stream, NODE_IOC_SET_CHANNEL, g_adda_loop_player->channel);
|
||||
/* printf("l:%x,%d\n",channel,err); */
|
||||
return err;
|
||||
} else {
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static int adda_loop_get_adc_num(void)
|
||||
{
|
||||
u8 ch_num = 0;
|
||||
struct adc_file_cfg temp_cfg = {0};
|
||||
char mode_index = 0;
|
||||
char cfg_index = 0;//目标配置项序号
|
||||
struct cfg_info info = {0};
|
||||
int err = jlstream_read_form_node_info_base(mode_index, "adda_adc", cfg_index, &info);
|
||||
if (err == 0) {
|
||||
jlstream_read_form_cfg_data(&info, &temp_cfg);
|
||||
} else {
|
||||
printf("adda_adc_file read cfg data err !!!\n");
|
||||
}
|
||||
for (int i = 0; i < AUDIO_ADC_MIC_MAX_NUM; i++) {
|
||||
if (temp_cfg.mic_en_map & BIT(i)) {
|
||||
ch_num ++;
|
||||
}
|
||||
}
|
||||
return ch_num;
|
||||
}
|
||||
|
||||
|
||||
int adda_loop_player_open()
|
||||
{
|
||||
int err;
|
||||
struct adda_loop_player *player;
|
||||
if (g_adda_loop_player) {
|
||||
return 0;
|
||||
}
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"adda_loop");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
player = malloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
|
||||
|
||||
if (!player->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
//设置中断点数
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, AUDIO_ADC_IRQ_POINTS);
|
||||
|
||||
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_NODE_CONFIG, adda_loop_get_adc_num());
|
||||
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_VOCAL_TRACK_SYNTHESIS, NODE_IOC_SET_PRIV_FMT, AUDIO_ADC_IRQ_POINTS);//四声道时,指定声道合并单个声道的点数
|
||||
|
||||
player->channel = AUDIO_CH_L;
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, player->channel);
|
||||
jlstream_set_callback(player->stream, player->stream, adda_loop_player_callback);
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_ADDA_LOOP);
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
g_adda_loop_player = player;
|
||||
return 0;
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
bool adda_loop_player_runing()
|
||||
{
|
||||
return g_adda_loop_player != NULL;
|
||||
}
|
||||
|
||||
|
||||
void adda_loop_player_close()
|
||||
{
|
||||
struct adda_loop_player *player = g_adda_loop_player;
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
jlstream_stop(player->stream, 50);
|
||||
jlstream_release(player->stream);
|
||||
|
||||
free(player);
|
||||
g_adda_loop_player = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"adda_loop");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".ai_rx_player.data.bss")
|
||||
#pragma data_seg(".ai_rx_player.data")
|
||||
#pragma const_seg(".ai_rx_player.text.const")
|
||||
#pragma code_seg(".ai_rx_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "media/audio_base.h"
|
||||
#include "system/includes.h"
|
||||
/* #include "sdk_config.h" */
|
||||
#include "app_config.h"
|
||||
#include "audio_config_def.h"
|
||||
#include "ai_rx_player.h"
|
||||
#include "jldemuxer.h"
|
||||
/* #include "rcsp_translator.h" */
|
||||
/* #include "classic/tws_api.h" */
|
||||
|
||||
#if TCFG_AI_RX_NODE_ENABLE
|
||||
|
||||
struct ai_rx_player {
|
||||
struct jlstream *stream;
|
||||
void *file;
|
||||
struct list_head entry;
|
||||
enum stream_scene scene;
|
||||
u8 *bt_addr;
|
||||
u8 read_err;
|
||||
u8 source;
|
||||
u8 type;
|
||||
int channel; //记录当前是tws左声道还是右声道
|
||||
};
|
||||
|
||||
extern int CONFIG_BTCTLER_TWS_ENABLE;
|
||||
|
||||
static struct list_head g_ai_rx_player_list = LIST_HEAD_INIT(g_ai_rx_player_list);
|
||||
const struct stream_file_ops ai_file_ops;
|
||||
|
||||
#define list_for_each_ai_rx_player(p) \
|
||||
list_for_each_entry(p, &g_ai_rx_player_list, entry)
|
||||
|
||||
static void ai_rx_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct ai_rx_player *player = (struct ai_rx_player *)private_data;
|
||||
|
||||
printf("ai_rx_player_callback, event: %d\n", event);
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ai_file_read(void *file, u8 *buf, int len)
|
||||
{
|
||||
int offset = 0;
|
||||
struct ai_rx_player *player = (struct ai_rx_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 ai_file_seek(void *file, int offset, int fromwhere)
|
||||
{
|
||||
struct ai_rx_player *player = (struct ai_rx_player *)file;
|
||||
return fseek(player->file, offset, fromwhere);
|
||||
}
|
||||
|
||||
int ai_file_flen(void *file)
|
||||
{
|
||||
struct ai_rx_player *player = (struct ai_rx_player *)file;
|
||||
u32 len = 0;
|
||||
if (player->file) {
|
||||
len = flen(player->file);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int ai_file_close(void *file)
|
||||
{
|
||||
struct ai_rx_player *player = (struct ai_rx_player *)file;
|
||||
|
||||
if (player->file) {
|
||||
fclose(player->file);
|
||||
player->file = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ai_file_get_fmt(void *file, struct stream_fmt *fmt)
|
||||
{
|
||||
u8 name[16];
|
||||
struct ai_rx_player *player = (struct ai_rx_player *)file;
|
||||
|
||||
fget_name(player->file, name, 16);
|
||||
struct stream_file_info info = {
|
||||
.file = player,
|
||||
.fname = (char *)name,
|
||||
.ops = &ai_file_ops,
|
||||
.scene = player->scene,
|
||||
};
|
||||
int err = jldemuxer_get_tone_file_fmt(&info, fmt);
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct stream_file_ops ai_file_ops = {
|
||||
.read = ai_file_read,
|
||||
.seek = ai_file_seek,
|
||||
.close = ai_file_close,
|
||||
.get_fmt = ai_file_get_fmt,
|
||||
};
|
||||
|
||||
|
||||
|
||||
int ai_rx_player_open(void *file, u8 source, struct ai_rx_player_param *param)
|
||||
{
|
||||
int err;
|
||||
struct ai_rx_player *player;
|
||||
u16 uuid = 0;
|
||||
if (!param) {
|
||||
printf("ai_rx_player param is NULL \n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
u8 type = param->type;
|
||||
|
||||
list_for_each_ai_rx_player(player) {
|
||||
if (player->source == source) {
|
||||
printf("ai_rx_player id %x is opened\n", (u32)source);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == AI_SERVICE_CALL_DOWNSTREAM || type == AI_SERVICE_CALL_UPSTREAM) {
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_rx_call");
|
||||
} else if (type == AI_SERVICE_MEDIA) {
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_rx_media");
|
||||
} else {
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_voice");
|
||||
}
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
player = zalloc(sizeof(*player));
|
||||
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
player->file = (FILE *)file;
|
||||
player->scene = STREAM_SCENE_OPUS;
|
||||
|
||||
if (type == AI_SERVICE_CALL_DOWNSTREAM) {
|
||||
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AI_RX_ESCO_DOWN");
|
||||
} else if (type == AI_SERVICE_CALL_UPSTREAM) {
|
||||
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AI_RX_ESCO_UP");
|
||||
} else {
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_AI_RX);
|
||||
}
|
||||
if (!player->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
list_add_tail(&player->entry, &g_ai_rx_player_list);
|
||||
/* player->bt_addr = bt_addr; */
|
||||
player->source = source;
|
||||
player->type = type;
|
||||
|
||||
jlstream_set_callback(player->stream, player, ai_rx_player_callback);
|
||||
if (type == AI_SERVICE_CALL_DOWNSTREAM || type == AI_SERVICE_CALL_UPSTREAM) {
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_ESCO);
|
||||
} else if (type == AI_SERVICE_MEDIA) {
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_A2DP);
|
||||
} else {
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_AI_VOICE);
|
||||
|
||||
}
|
||||
#if 0
|
||||
if (CONFIG_BTCTLER_TWS_ENABLE) {
|
||||
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
|
||||
player->channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, player->channel);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, AUDIO_CH_MIX);
|
||||
/* jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_BTADDR, (int)bt_addr); */
|
||||
jlstream_set_scene(player->stream, player->scene);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PARAM, (int)source);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_FMT, (int)param);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
|
||||
NODE_IOC_SET_FILE_LEN, (int)ai_file_flen(player));
|
||||
|
||||
|
||||
#if TCFG_DEC_OGG_OPUS_ENABLE
|
||||
jlstream_set_dec_file(player->stream, player, &ai_file_ops);
|
||||
#else
|
||||
jlstream_set_dec_file(player->stream, player->file, &ai_file_ops);
|
||||
|
||||
#endif
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
bool ai_rx_player_runing(u8 source)
|
||||
{
|
||||
struct ai_rx_player *player;
|
||||
list_for_each_ai_rx_player(player) {
|
||||
if (player->source == source) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void ai_rx_player_close(u8 source)
|
||||
{
|
||||
struct ai_rx_player *player;
|
||||
u8 found = 0;
|
||||
const char *pipeline;
|
||||
|
||||
list_for_each_ai_rx_player(player) {
|
||||
if (player->source == source) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
if (player->type == AI_SERVICE_CALL_DOWNSTREAM || player->type == AI_SERVICE_CALL_UPSTREAM) {
|
||||
pipeline = "ai_rx_call";
|
||||
} else if (player->type == AI_SERVICE_MEDIA) {
|
||||
pipeline = "ai_rx_media";
|
||||
} else {
|
||||
pipeline = "ai_voice";
|
||||
}
|
||||
jlstream_stop(player->stream, 0);
|
||||
jlstream_release(player->stream);
|
||||
|
||||
list_del(&player->entry);
|
||||
free(player);
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)pipeline);
|
||||
}
|
||||
/************************测试代码******************************/
|
||||
#if 0
|
||||
#include "system/includes.h"
|
||||
#define SD_ROOT_PATH "storage/sd0/C/"
|
||||
#define FILE_NAME SD_ROOT_PATH"bd.ogg"
|
||||
FILE *opus_debug = NULL;
|
||||
|
||||
FILE *ai_get_file()
|
||||
{
|
||||
opus_debug = fopen(FILE_NAME, "r");
|
||||
if (opus_debug == NULL) {
|
||||
ASSERT(0, "opus_debug %p ", opus_debug);
|
||||
}
|
||||
return opus_debug;
|
||||
}
|
||||
void ai_rx_debug()
|
||||
{
|
||||
struct ai_rx_player_param param = {0};
|
||||
param.coding_type = AUDIO_CODING_OPUS;
|
||||
param.channel_mode = AUDIO_CH_MIX;
|
||||
param.sample_rate = 16000;
|
||||
param.bit_rate = 16000;
|
||||
param.type = AI_SERVICE_VOICE;
|
||||
param.frame_dms = 200; //20ms一帧
|
||||
extern FILE *ai_get_file();
|
||||
ai_rx_player_open((void *)ai_get_file(), 0, ¶m);
|
||||
|
||||
extern void audio_app_volume_set(u8 state, s16 volume, u8 fade);
|
||||
audio_app_volume_set(APP_AUDIO_STATE_MUSIC, 100, 1);
|
||||
}
|
||||
|
||||
|
||||
void ai_rx_close()
|
||||
{
|
||||
ai_rx_player_close(0);
|
||||
fclose(opus_debug);
|
||||
}
|
||||
#endif
|
||||
#endif /*TCFG_AI_RX_NODE_ENABLE*/
|
||||
@@ -0,0 +1,295 @@
|
||||
|
||||
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".avi_audio_player.data.bss")
|
||||
#pragma data_seg(".avi_audio_player.data")
|
||||
#pragma const_seg(".avi_audio_player.text.const")
|
||||
#pragma code_seg(".avi_audio_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "media/audio_base.h"
|
||||
#include "system/includes.h"
|
||||
/* #include "sdk_config.h" */
|
||||
#include "app_config.h"
|
||||
#include "audio_config_def.h"
|
||||
#include "avi_audio_player.h"
|
||||
//#include "avi_audio_player.h"
|
||||
#include "jldemuxer.h"
|
||||
/* #include "rcsp_translator.h" */
|
||||
/* #include "classic/tws_api.h" */
|
||||
|
||||
#if TCFG_VIDEO_DIAL_ENABLE
|
||||
|
||||
struct avi_audio_player {
|
||||
struct jlstream *stream;
|
||||
void *file;
|
||||
struct list_head entry;
|
||||
enum stream_scene scene;
|
||||
u8 *bt_addr;
|
||||
u8 read_err;
|
||||
u8 source;
|
||||
u8 type;
|
||||
int channel; //记录当前是tws左声道还是右声道
|
||||
};
|
||||
|
||||
extern int CONFIG_BTCTLER_TWS_ENABLE;
|
||||
|
||||
static struct list_head g_avi_audio_player_list = LIST_HEAD_INIT(g_avi_audio_player_list);
|
||||
const struct stream_file_ops avi_file_ops;
|
||||
|
||||
#define list_for_each_avi_audio_player(p) \
|
||||
list_for_each_entry(p, &g_avi_audio_player_list, entry)
|
||||
|
||||
static void avi_audio_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct avi_audio_player *player = (struct avi_audio_player *)private_data;
|
||||
|
||||
printf("avi_audio_player_callback, event: %d\n", event);
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int avi_file_read(void *file, u8 *buf, int len)
|
||||
{
|
||||
int offset = 0;
|
||||
struct avi_audio_player *player = (struct avi_audio_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 avi_file_seek(void *file, int offset, int fromwhere)
|
||||
{
|
||||
struct avi_audio_player *player = (struct avi_audio_player *)file;
|
||||
return fseek(player->file, offset, fromwhere);
|
||||
}
|
||||
|
||||
int avi_file_flen(void *file)
|
||||
{
|
||||
struct avi_audio_player *player = (struct avi_audio_player *)file;
|
||||
u32 len = 0;
|
||||
if (player->file) {
|
||||
len = flen(player->file);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int avi_file_close(void *file)
|
||||
{
|
||||
struct avi_audio_player *player = (struct avi_audio_player *)file;
|
||||
|
||||
if (player->file) {
|
||||
fclose(player->file);
|
||||
player->file = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avi_file_get_fmt(void *file, struct stream_fmt *fmt)
|
||||
{
|
||||
u8 name[16];
|
||||
struct avi_audio_player *player = (struct avi_audio_player *)file;
|
||||
|
||||
fget_name(player->file, name, 16);
|
||||
struct stream_file_info info = {
|
||||
.file = player,
|
||||
.fname = (char *)name,
|
||||
.ops = &avi_file_ops,
|
||||
.scene = player->scene,
|
||||
};
|
||||
int err = jldemuxer_get_tone_file_fmt(&info, fmt);
|
||||
printf("avi_file_get_fmt%p, err: %d\n", fmt, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct stream_file_ops avi_file_ops = {
|
||||
.read = avi_file_read,
|
||||
.seek = avi_file_seek,
|
||||
.close = avi_file_close,
|
||||
.get_fmt = avi_file_get_fmt,
|
||||
};
|
||||
|
||||
|
||||
|
||||
int avi_audio_player_open(void *file, u8 source, struct avi_audio_player_param *param)
|
||||
{
|
||||
printf("avi_audio_player_open, source: %x\n", source);
|
||||
int err;
|
||||
struct avi_audio_player *player;
|
||||
u16 uuid = 0;
|
||||
if (!param) {
|
||||
printf("avi_audio_player param is NULL \n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
u8 type = param->type;
|
||||
|
||||
list_for_each_avi_audio_player(player) {
|
||||
if (player->source == source) {
|
||||
printf("avi_audio_player id %x is opened\n", (u32)source);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == AVI_SERVICE_CALL_DOWNSTREAM || type == AVI_SERVICE_CALL_UPSTREAM) {
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"avi_rx_call");
|
||||
} else if (type == AVI_SERVICE_MEDIA) {
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"avi_rx_media");
|
||||
} else {
|
||||
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"avi_voice");
|
||||
}
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
player = zalloc(sizeof(*player));
|
||||
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
player->file = (FILE *)file;
|
||||
player->scene = STREAM_SCENE_OPUS;
|
||||
|
||||
if (type == AVI_SERVICE_CALL_DOWNSTREAM) {
|
||||
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AVI_RX_ESCO_DOWN");
|
||||
} else if (type == AVI_SERVICE_CALL_UPSTREAM) {
|
||||
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AVI_RX_ESCO_UP");
|
||||
} else {
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_VIDEO_DEC);
|
||||
}
|
||||
if (!player->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
list_add_tail(&player->entry, &g_avi_audio_player_list);
|
||||
/* player->bt_addr = bt_addr; */
|
||||
player->source = source;
|
||||
player->type = type;
|
||||
|
||||
jlstream_set_callback(player->stream, player, avi_audio_player_callback);
|
||||
if (type == AVI_SERVICE_CALL_DOWNSTREAM || type == AVI_SERVICE_CALL_UPSTREAM) {
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_ESCO);
|
||||
} else if (type == AVI_SERVICE_MEDIA) {
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_A2DP);
|
||||
} else {
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_AI_VOICE);
|
||||
|
||||
}
|
||||
#if 0
|
||||
if (CONFIG_BTCTLER_TWS_ENABLE) {
|
||||
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
|
||||
player->channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, player->channel);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, AUDIO_CH_MIX);
|
||||
/* jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_BTADDR, (int)bt_addr); */
|
||||
jlstream_set_scene(player->stream, player->scene);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PARAM, (int)source);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_FMT, (int)param);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
|
||||
NODE_IOC_SET_FILE_LEN, (int)avi_file_flen(player));
|
||||
|
||||
|
||||
#if TCFG_DEC_OGG_OPUS_ENABLE
|
||||
jlstream_set_dec_file(player->stream, player, &avi_file_ops);
|
||||
#else
|
||||
// jlstream_set_dec_file(player->stream, player->file, &avi_file_ops);
|
||||
|
||||
#endif
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
bool avi_audio_player_runing(u8 source)
|
||||
{
|
||||
struct avi_audio_player *player;
|
||||
list_for_each_avi_audio_player(player) {
|
||||
if (player->source == source) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void avi_audio_player_close(u8 source)
|
||||
{
|
||||
struct avi_audio_player *player;
|
||||
u8 found = 0;
|
||||
const char *pipeline;
|
||||
|
||||
list_for_each_avi_audio_player(player) {
|
||||
if (player->source == source) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
if (player->type == AVI_SERVICE_CALL_DOWNSTREAM || player->type == AVI_SERVICE_CALL_UPSTREAM) {
|
||||
pipeline = "avi_rx_call";
|
||||
} else if (player->type == AVI_SERVICE_MEDIA) {
|
||||
pipeline = "avi_rx_media";
|
||||
} else {
|
||||
pipeline = "avi_voice";
|
||||
}
|
||||
jlstream_stop(player->stream, 0);
|
||||
jlstream_release(player->stream);
|
||||
|
||||
list_del(&player->entry);
|
||||
free(player);
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)pipeline);
|
||||
}
|
||||
#endif /*TCFG_AVU_RX_NODE_ENABLE*/
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".dev_flow_player.data.bss")
|
||||
#pragma data_seg(".dev_flow_player.data")
|
||||
#pragma const_seg(".dev_flow_player.text.const")
|
||||
#pragma code_seg(".dev_flow_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config_def.h"
|
||||
#include "dev_flow_player.h"
|
||||
|
||||
struct dev_flow_player {
|
||||
struct jlstream *stream;
|
||||
};
|
||||
|
||||
static struct dev_flow_player *g_dev_flow_player = NULL;
|
||||
|
||||
|
||||
static void dev_flow_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct dev_flow_player *player = g_dev_flow_player;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//自定义数据流播放器 启动
|
||||
int dev_flow_player_open(void)
|
||||
{
|
||||
int err;
|
||||
struct dev_flow_player *player;
|
||||
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"dev_flow");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
player = malloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
导入自定义音频流的源节点UUID,如下自定义源节点为NODE_UUID_SOURCE_DEV,
|
||||
若是其他源节点,需使用对应节点的UUID,如ADC节点则为NODE_UUID_ADC
|
||||
*/
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_SOURCE_DEV0);
|
||||
/* player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_SOURCE_DEV1); */
|
||||
|
||||
if (!player->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
//设置当前数据对应节点的特性
|
||||
/* err = jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, arg); */
|
||||
|
||||
jlstream_set_callback(player->stream, player->stream, dev_flow_player_callback);
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_DEV_FLOW);
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
g_dev_flow_player = player;
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
//自定义数据流播放器 查询是否活动
|
||||
bool dev_flow_player_runing(void)
|
||||
{
|
||||
return g_dev_flow_player != NULL;
|
||||
}
|
||||
|
||||
|
||||
//自定义数据流播放器 关闭
|
||||
void dev_flow_player_close(void)
|
||||
{
|
||||
struct dev_flow_player *player = g_dev_flow_player;
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
jlstream_stop(player->stream, 50);
|
||||
jlstream_release(player->stream);
|
||||
|
||||
free(player);
|
||||
g_dev_flow_player = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"dev_flow");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".esco_player.data.bss")
|
||||
#pragma data_seg(".esco_player.data")
|
||||
#pragma const_seg(".esco_player.text.const")
|
||||
#pragma code_seg(".esco_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "esco_player.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
|
||||
#include "icsd_adt_app.h"
|
||||
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
|
||||
|
||||
struct esco_player {
|
||||
u8 bt_addr[6];
|
||||
u8 suspend;
|
||||
struct jlstream *stream;
|
||||
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
|
||||
u8 icsd_adt_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct esco_player *g_esco_player = NULL;
|
||||
|
||||
|
||||
static void esco_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct esco_player *player = g_esco_player;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int esco_player_open(u8 *bt_addr)
|
||||
{
|
||||
int err;
|
||||
struct esco_player *player;
|
||||
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"esco");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
player = malloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ESCO_RX);
|
||||
if (!player->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
#if TCFG_ESCO_DL_CVSD_SR_USE_16K
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_BT_AUDIO_SYNC, NODE_IOC_SET_PRIV_FMT, TCFG_ESCO_DL_CVSD_SR_USE_16K);
|
||||
#endif /*TCFG_ESCO_DL_CVSD_SR_USE_16K*/
|
||||
|
||||
jlstream_set_callback(player->stream, player->stream, esco_player_callback);
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_ESCO);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_BTADDR, (int)bt_addr);
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
memcpy(player->bt_addr, bt_addr, 6);
|
||||
g_esco_player = player;
|
||||
|
||||
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
|
||||
/*通话前关闭adt*/
|
||||
player->icsd_adt_state = audio_icsd_adt_is_running();
|
||||
if (player->icsd_adt_state) {
|
||||
audio_icsd_adt_close(0, 1);
|
||||
}
|
||||
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
bool esco_player_runing()
|
||||
{
|
||||
return g_esco_player != NULL;
|
||||
}
|
||||
|
||||
int esco_player_get_btaddr(u8 *btaddr)
|
||||
{
|
||||
if (g_esco_player) {
|
||||
memcpy(btaddr, g_esco_player->bt_addr, 6);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int esco_player_suspend(u8 *bt_addr)
|
||||
{
|
||||
if (g_esco_player && (memcmp(g_esco_player->bt_addr, bt_addr, 6) == 0)) {
|
||||
/*jlstream_ioctl(g_esco_player->stream, NODE_IOC_SUSPEND, 0);*/
|
||||
if (!g_esco_player->suspend) {
|
||||
jlstream_stop(g_esco_player->stream, 0);
|
||||
jlstream_release(g_esco_player->stream);
|
||||
lmp_private_esco_suspend_resume(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int esco_player_start(u8 *bt_addr)
|
||||
{
|
||||
if (g_esco_player && (memcmp(g_esco_player->bt_addr, bt_addr, 6) == 0)) {
|
||||
/*jlstream_ioctl(g_esco_player->stream, NODE_IOC_START, 0);*/
|
||||
if (g_esco_player->suspend) {
|
||||
esco_player_close();
|
||||
esco_player_open(bt_addr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
ESCO状态检测,
|
||||
param:btaddr 目标蓝牙地址, 传NULL则只检查耳机状态
|
||||
*/
|
||||
int esco_player_is_playing(u8 *btaddr)
|
||||
{
|
||||
int cur_addr = 1;
|
||||
if (btaddr && g_esco_player) { //当前蓝牙地址检测
|
||||
cur_addr = (!memcmp(btaddr, g_esco_player->bt_addr, 6));
|
||||
}
|
||||
if (g_esco_player && cur_addr) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void esco_player_close()
|
||||
{
|
||||
struct esco_player *player = g_esco_player;
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
jlstream_stop(player->stream, 0);
|
||||
jlstream_release(player->stream);
|
||||
|
||||
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
|
||||
if (player->icsd_adt_state) {
|
||||
audio_icsd_adt_open(0);
|
||||
}
|
||||
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
|
||||
free(player);
|
||||
g_esco_player = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"esco");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,838 @@
|
||||
#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
|
||||
@@ -0,0 +1,106 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".key_tone_player.data.bss")
|
||||
#pragma data_seg(".key_tone_player.data")
|
||||
#pragma const_seg(".key_tone_player.text.const")
|
||||
#pragma code_seg(".key_tone_player.text")
|
||||
#endif
|
||||
#include "tone_player.h"
|
||||
#include "os/os_api.h"
|
||||
#include "system/init.h"
|
||||
#include "app_config.h"
|
||||
|
||||
static struct tone_player *g_player = NULL;
|
||||
static OS_MUTEX g_mutex;
|
||||
static u8 g_play_cnt = 0;
|
||||
|
||||
extern const struct stream_file_ops tone_file_ops;
|
||||
|
||||
static void key_tone_player_callback(void *_player_id, int event)
|
||||
{
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
case STREAM_EVENT_PREEMPTED:
|
||||
break;
|
||||
case STREAM_EVENT_NEGOTIATE_FAILD:
|
||||
case STREAM_EVENT_STOP:
|
||||
struct tone_player *player = g_player;
|
||||
if (!player || player->player_id != (u8)_player_id) {
|
||||
break;
|
||||
}
|
||||
if (g_play_cnt) {
|
||||
g_play_cnt--;
|
||||
int err = jlstream_start(player->stream);
|
||||
if (err == 0) {
|
||||
break;
|
||||
}
|
||||
g_play_cnt = 0;
|
||||
}
|
||||
g_player = NULL;
|
||||
jlstream_release(player->stream);
|
||||
free(player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int key_tone_player_start(struct tone_player *player)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"tone");
|
||||
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_KEY_TONE);
|
||||
if (!player->stream) {
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
int player_id = player->player_id;
|
||||
jlstream_set_callback(player->stream, (void *)player_id, key_tone_player_callback);
|
||||
jlstream_set_scene(player->stream, player->scene);
|
||||
jlstream_set_dec_file(player->stream, player, &tone_file_ops);
|
||||
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit;
|
||||
}
|
||||
g_player = player;
|
||||
|
||||
return 0;
|
||||
|
||||
__exit:
|
||||
if (player->stream) {
|
||||
jlstream_release(player->stream);
|
||||
}
|
||||
if (player->file) {
|
||||
resfile_close(player->file);
|
||||
player->file = NULL;
|
||||
}
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
int play_key_tone_file(const char *file_name)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
if (g_player) {
|
||||
if (g_play_cnt < 10) {
|
||||
g_play_cnt++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
int err = tone_player_init(player, file_name);
|
||||
if (err) {
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
player->scene = STREAM_SCENE_KEY_TONE;
|
||||
|
||||
return key_tone_player_start(player);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".pc_spk_player.data.bss")
|
||||
#pragma data_seg(".pc_spk_player.data")
|
||||
#pragma const_seg(".pc_spk_player.text.const")
|
||||
#pragma code_seg(".pc_spk_player.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "sdk_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "system/includes.h"
|
||||
#include "pc_spk_player.h"
|
||||
#include "pc_spk_file.h"
|
||||
#include "app_config.h"
|
||||
#include "app_main.h"
|
||||
#include "effects/audio_pitchspeed.h"
|
||||
#include "effect/effects_default_param.h"
|
||||
#include "audio_config.h"
|
||||
#include "scene_switch.h"
|
||||
#include "uac_stream.h"
|
||||
#include "audio_cvp.h"
|
||||
|
||||
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN)
|
||||
#include "le_broadcast.h"
|
||||
#include "app_le_broadcast.h"
|
||||
#endif
|
||||
|
||||
#if (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
|
||||
#include "app_le_auracast.h"
|
||||
#endif
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[pcspk]"
|
||||
#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_USB_SLAVE_AUDIO_SPK_ENABLE
|
||||
|
||||
typedef enum {
|
||||
PC_SPK_STA_CLOSE,
|
||||
PC_SPK_STA_WAIT_CLOSE,
|
||||
PC_SPK_STA_OPEN,
|
||||
PC_SPK_STA_WAIT_OPEN,
|
||||
} pc_spk_state_t;
|
||||
pc_spk_state_t g_pc_spk_state;
|
||||
|
||||
struct pc_spk_player {
|
||||
struct jlstream *stream;
|
||||
s8 pc_spk_pitch_mode;
|
||||
};
|
||||
static struct pc_spk_player *g_pc_spk_player = NULL;
|
||||
|
||||
extern void dac_try_power_on_task_delete();
|
||||
|
||||
static void pc_spk_player_callback(void *private_data, int event)
|
||||
{
|
||||
struct pc_spk_player *player = g_pc_spk_player;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
|
||||
#if TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE)
|
||||
//先开pc mic,后开spk,需要取消忽略外部数据,重启aec
|
||||
if (audio_aec_status()) {
|
||||
audio_aec_reboot(0);
|
||||
audio_cvp_ref_data_align_reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (app_get_current_mode()->name == APP_MODE_PC) {
|
||||
s16 cur_vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
u16 l_vol = 0, r_vol = 0;
|
||||
uac_speaker_stream_get_volume(&l_vol, &r_vol);
|
||||
if (cur_vol != (r_vol + l_vol) / 2) {
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, (r_vol + l_vol) / 2, 1);
|
||||
}
|
||||
}
|
||||
#if TCFG_VOCAL_REMOVER_NODE_ENABLE
|
||||
musci_vocal_remover_update_parm();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @description: 打开 pc spk 数据流
|
||||
* @return:0 - 成功。其它值失败
|
||||
* @node:
|
||||
*/
|
||||
int pc_spk_player_open(void)
|
||||
{
|
||||
u32 rets_addr;
|
||||
__asm__ volatile("%0 = rets ;" : "=r"(rets_addr));
|
||||
|
||||
int err = 0;
|
||||
struct pc_spk_player *player = NULL;;
|
||||
|
||||
if (g_pc_spk_player || !app_in_mode(APP_MODE_PC)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"pc_spk");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
player->pc_spk_pitch_mode = PITCH_0;
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_PC_SPK);
|
||||
|
||||
if (!player->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
u16 l_vol = 0, r_vol = 0;
|
||||
uac_speaker_stream_get_volume(&l_vol, &r_vol);
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, (r_vol + l_vol) / 2, 1);
|
||||
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 192);
|
||||
jlstream_set_callback(player->stream, player->stream, pc_spk_player_callback);
|
||||
jlstream_set_scene(player->stream, STREAM_SCENE_PC_SPK);
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
} else {
|
||||
dac_try_power_on_task_delete();
|
||||
}
|
||||
|
||||
g_pc_spk_state = PC_SPK_STA_OPEN;
|
||||
g_pc_spk_player = player;
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
// 返回1说明player 在运行
|
||||
bool pc_spk_player_runing()
|
||||
{
|
||||
return g_pc_spk_player != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @description: 关闭spk 数据流
|
||||
* @return:
|
||||
* @node:
|
||||
*/
|
||||
void pc_spk_player_close(void)
|
||||
{
|
||||
struct pc_spk_player *player = g_pc_spk_player;
|
||||
|
||||
if (!player) {
|
||||
if (g_pc_spk_state == PC_SPK_STA_WAIT_OPEN || g_pc_spk_state == PC_SPK_STA_OPEN) {
|
||||
//可能在切到其它模式瞬间有spk音频起来,打开spk采用的是信号量方式打开,导致关闭spk的动作比打开的动作更提前
|
||||
log_debug("err, [%s], player_wait_open_flag:1!\n", __func__);
|
||||
pcspk_close_player_by_taskq();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0//pc + bt 通过mixer叠加的环境, 因usbrx已经停止,无法驱动数据流。需手动提前将当前的mixer ch关闭
|
||||
struct mixer_ch_pause pause = {0};
|
||||
pause.ch_idx = 7;
|
||||
jlstream_set_node_param(NODE_UUID_MIXER, "MIXER27", &pause, sizeof(pause));
|
||||
#endif
|
||||
jlstream_stop(player->stream, 0);
|
||||
jlstream_release(player->stream);
|
||||
free(player);
|
||||
player = NULL;
|
||||
g_pc_spk_player = NULL;
|
||||
#if TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE)
|
||||
if (audio_aec_status()) {
|
||||
//忽略参考数据
|
||||
audio_cvp_ioctl(CVP_OUTWAY_REF_IGNORE, 1, NULL);
|
||||
audio_cvp_ref_data_align_reset();
|
||||
}
|
||||
#endif
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"pc_spk");
|
||||
|
||||
g_pc_spk_state = PC_SPK_STA_CLOSE;
|
||||
}
|
||||
|
||||
static void pc_spk_player_restert(void)
|
||||
{
|
||||
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN)
|
||||
if (!get_broadcast_role()) {
|
||||
if (g_pc_spk_state == PC_SPK_STA_OPEN) {
|
||||
pc_spk_player_close();
|
||||
pc_spk_player_open();
|
||||
}
|
||||
} else { //广播模式则重启广播数据流
|
||||
le_audio_scene_deal(LE_AUDIO_MUSIC_STOP);
|
||||
le_audio_scene_deal(LE_AUDIO_MUSIC_START);
|
||||
}
|
||||
#elif (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
|
||||
if (!get_auracast_role()) {
|
||||
if (g_pc_spk_state == PC_SPK_STA_OPEN) {
|
||||
pc_spk_player_close();
|
||||
pc_spk_player_open();
|
||||
}
|
||||
} else { //广播模式则重启广播数据流
|
||||
le_audio_scene_deal(LE_AUDIO_MUSIC_STOP);
|
||||
le_audio_scene_deal(LE_AUDIO_MUSIC_START);
|
||||
}
|
||||
#else
|
||||
if (g_pc_spk_state == PC_SPK_STA_OPEN) {
|
||||
pc_spk_player_close();
|
||||
pc_spk_player_open();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int pcspk_close_player_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = 0;
|
||||
if (g_pc_spk_state == PC_SPK_STA_OPEN ||
|
||||
g_pc_spk_state == PC_SPK_STA_WAIT_OPEN) {
|
||||
|
||||
g_pc_spk_state = PC_SPK_STA_WAIT_CLOSE;
|
||||
msg[0] = (int)pc_spk_player_close;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int pcspk_open_player_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = 0;
|
||||
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN) && !TCFG_KBOX_1T3_MODE_EN
|
||||
if ((g_pc_spk_state == PC_SPK_STA_CLOSE ||
|
||||
g_pc_spk_state == PC_SPK_STA_WAIT_CLOSE) && !get_broadcast_role()) {
|
||||
#elif (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
|
||||
if ((g_pc_spk_state == PC_SPK_STA_CLOSE ||
|
||||
g_pc_spk_state == PC_SPK_STA_WAIT_CLOSE) && !get_auracast_role()) {
|
||||
#else
|
||||
if (g_pc_spk_state == PC_SPK_STA_CLOSE ||
|
||||
g_pc_spk_state == PC_SPK_STA_WAIT_CLOSE) {
|
||||
#endif
|
||||
g_pc_spk_state = PC_SPK_STA_WAIT_OPEN;
|
||||
msg[0] = (int)pc_spk_player_open;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pcspk_restart_player_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = 0;
|
||||
msg[0] = (int)pc_spk_player_restert;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pc_spk_set_volume(void)
|
||||
{
|
||||
if (app_get_current_mode()->name == APP_MODE_PC) {
|
||||
s16 cur_vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
u16 l_vol = 0, r_vol = 0;
|
||||
uac_speaker_stream_get_volume(&l_vol, &r_vol);
|
||||
if (cur_vol != ((l_vol + r_vol) / 2)) {
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, ((l_vol + r_vol) / 2), 1);
|
||||
log_debug(">>> pc vol: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pcspk_set_volume_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = -1;
|
||||
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
|
||||
msg[0] = (int)pc_spk_set_volume;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool pc_spk_player_runing()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".reference_time.data.bss")
|
||||
#pragma data_seg(".reference_time.data")
|
||||
#pragma const_seg(".reference_time.text.const")
|
||||
#pragma code_seg(".reference_time.text")
|
||||
#endif
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file reference_time.c
|
||||
*
|
||||
* \brief 提供音频参考时钟选择的接口函数实体与管理
|
||||
*
|
||||
* Copyright (c) 2011-2022 ZhuHai Jieli Technology Co.,Ltd.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include "reference_time.h"
|
||||
#include "system/includes.h"
|
||||
/* #include "le_audio_stream.h" */
|
||||
|
||||
/*
|
||||
* 关于优先级选择:
|
||||
* 手机的网络时钟优先级最高,无手机网络的情况下选择TWS网络
|
||||
*/
|
||||
static LIST_HEAD(reference_head);
|
||||
static u8 local_network = 0xff;
|
||||
static u8 local_net_addr[6];
|
||||
static u8 local_network_id = 1;
|
||||
extern const int LE_AUDIO_TIME_ENABLE;
|
||||
|
||||
struct reference_clock {
|
||||
u8 id;
|
||||
u8 network;
|
||||
union {
|
||||
u8 net_addr[6];
|
||||
void *le_addr;
|
||||
};
|
||||
struct list_head entry;
|
||||
};
|
||||
|
||||
extern void bt_audio_reference_clock_select(void *addr, u8 network);
|
||||
extern u32 bt_audio_reference_clock_time(u8 network);
|
||||
extern u32 bt_audio_reference_clock_remapping(void *src_addr, u8 src_network, void *dst_addr, u8 dst_network, u32 clock);
|
||||
extern u8 bt_audio_reference_link_exist(void *addr, u8 network);
|
||||
|
||||
//le audio相关函数弱定义
|
||||
__attribute__((weak))
|
||||
int le_audio_stream_clock_select(void *le_audio)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak))
|
||||
u32 le_audio_stream_current_time(void *le_audio)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak))
|
||||
int le_audio_stream_get_latch_time(void *le_audio, u32 *time, u16 *us_1_12th, u32 *event)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
__attribute__((weak))
|
||||
void le_audio_stream_latch_time_enable(void *le_audio)
|
||||
{
|
||||
printf("empty fun %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
int audio_reference_clock_select(void *addr, u8 network)
|
||||
{
|
||||
struct reference_clock *reference_clock = (struct reference_clock *)zalloc(sizeof(struct reference_clock));
|
||||
struct reference_clock *clk;
|
||||
u8 reset_clock = 1;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
if (network > 2) {
|
||||
local_irq_enable();
|
||||
free(reference_clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (list_empty(&reference_head) || network == 0) {
|
||||
reference_clock->network = network;
|
||||
if (LE_AUDIO_TIME_ENABLE && network == 2) {
|
||||
reference_clock->le_addr = addr;
|
||||
} else {
|
||||
if (addr == NULL) {
|
||||
memset(reference_clock->net_addr, 0x0, sizeof(reference_clock->net_addr));
|
||||
} else {
|
||||
memcpy(reference_clock->net_addr, addr, sizeof(reference_clock->net_addr));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == 0 && bt_audio_reference_link_exist(clk->net_addr, clk->network)) {
|
||||
reference_clock->network = clk->network;
|
||||
memcpy(reference_clock->net_addr, clk->net_addr, sizeof(reference_clock->net_addr));
|
||||
reset_clock = 0;
|
||||
} else {
|
||||
reference_clock->network = network;
|
||||
if (LE_AUDIO_TIME_ENABLE && network == 2) {
|
||||
reference_clock->le_addr = addr;
|
||||
} else {
|
||||
if (addr == NULL) {
|
||||
memset(reference_clock->net_addr, 0x0, sizeof(reference_clock->net_addr));
|
||||
} else {
|
||||
memcpy(reference_clock->net_addr, addr, sizeof(reference_clock->net_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_add(&reference_clock->entry, &reference_head);
|
||||
reference_clock->id = local_network_id;
|
||||
if (++local_network_id == 0) {
|
||||
local_network_id++;
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
if (reset_clock) {
|
||||
if (LE_AUDIO_TIME_ENABLE && reference_clock->network == 2) {
|
||||
le_audio_stream_clock_select(reference_clock->le_addr);
|
||||
} else {
|
||||
bt_audio_reference_clock_select(reference_clock->net_addr, reference_clock->network);
|
||||
}
|
||||
}
|
||||
|
||||
return reference_clock->id;
|
||||
}
|
||||
|
||||
u32 audio_reference_clock_time(void)
|
||||
{
|
||||
if (!list_empty(&reference_head)) {
|
||||
struct reference_clock *clk;
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (LE_AUDIO_TIME_ENABLE && clk->network == 2) {
|
||||
return le_audio_stream_current_time(clk->le_addr);
|
||||
}
|
||||
return bt_audio_reference_clock_time(clk->network);
|
||||
}
|
||||
|
||||
return bt_audio_reference_clock_time(local_network);
|
||||
}
|
||||
|
||||
u32 audio_reference_network_clock_time(u8 network)
|
||||
{
|
||||
return bt_audio_reference_clock_time(network);
|
||||
}
|
||||
|
||||
u8 audio_reference_network_exist(u8 id)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(clk, &reference_head, entry) {
|
||||
if (clk->id == id) {
|
||||
goto exist_detect;
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
|
||||
exist_detect:
|
||||
local_irq_enable();
|
||||
return bt_audio_reference_link_exist(clk->net_addr, clk->network);
|
||||
}
|
||||
|
||||
int le_audio_get_reference_latch_time(u32 *time, u16 *us_1_12th, u32 *event)
|
||||
{
|
||||
if (!LE_AUDIO_TIME_ENABLE) {
|
||||
return 0;
|
||||
}
|
||||
if (!list_empty(&reference_head)) {
|
||||
struct reference_clock *clk;
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == 2) {
|
||||
le_audio_stream_get_latch_time(clk->le_addr, time, us_1_12th, event);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void le_audio_reference_time_latch_enable(void)
|
||||
{
|
||||
if (!LE_AUDIO_TIME_ENABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!list_empty(&reference_head)) {
|
||||
struct reference_clock *clk;
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == 2) {
|
||||
le_audio_stream_latch_time_enable(clk->le_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 is_audio_reference_clock_enable(void)
|
||||
{
|
||||
return 0;
|
||||
/*return local_network == 0xff ? 0 : 1;*/
|
||||
}
|
||||
|
||||
u8 audio_reference_clock_network(void *addr)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
|
||||
if (list_empty(&reference_head)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network != 2 && addr) {
|
||||
memcpy(addr, clk->net_addr, 6);
|
||||
}
|
||||
|
||||
return clk->network;
|
||||
}
|
||||
|
||||
u8 audio_reference_clock_match(void *addr, u8 network)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
|
||||
if (list_empty(&reference_head)) {
|
||||
return 0;
|
||||
}
|
||||
clk = list_first_entry(&reference_head, struct reference_clock, entry);
|
||||
if (clk->network == network) {
|
||||
if (network == 0) {
|
||||
if (addr && memcmp(clk->net_addr, addr, 6) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 audio_reference_clock_remapping(u8 now_network, u8 dst_network, u32 clock)
|
||||
{
|
||||
void *now_addr = NULL;
|
||||
void *dst_addr = NULL;
|
||||
struct reference_clock *clk;
|
||||
|
||||
local_irq_disable();
|
||||
list_for_each_entry(clk, &reference_head, entry) {
|
||||
if (!now_addr && clk->network == now_network) {
|
||||
now_addr = clk->net_addr;
|
||||
}
|
||||
if (!dst_addr && clk->network == dst_network) {
|
||||
dst_addr = clk->net_addr;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
return bt_audio_reference_clock_remapping(now_addr, now_network, dst_addr, dst_network, clock);
|
||||
}
|
||||
|
||||
void audio_reference_clock_exit(u8 id)
|
||||
{
|
||||
struct reference_clock *clk;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(clk, &reference_head, entry) {
|
||||
if (clk->id == id) {
|
||||
goto delete;
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
return;
|
||||
delete:
|
||||
list_del(&clk->entry);
|
||||
free(clk);
|
||||
if (!list_empty(&reference_head)) {
|
||||
/*clk = list_first_entry(&reference_head, struct reference_clock, entry);*/
|
||||
/*bt_audio_reference_clock_select(clk->net_addr, clk->network);*/
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".ring_player.data.bss")
|
||||
#pragma data_seg(".ring_player.data")
|
||||
#pragma const_seg(".ring_player.text.const")
|
||||
#pragma code_seg(".ring_player.text")
|
||||
#endif
|
||||
#include "tone_player.h"
|
||||
#include "os/os_api.h"
|
||||
#include "system/init.h"
|
||||
#include "app_config.h"
|
||||
|
||||
static struct tone_player *g_ring_player = NULL;
|
||||
static OS_MUTEX g_ring_mutex;
|
||||
|
||||
extern const struct stream_file_ops tone_file_ops;
|
||||
|
||||
static void ring_player_callback(void *_player_id, int event)
|
||||
{
|
||||
struct tone_player *player = g_ring_player;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
os_mutex_pend(&g_ring_mutex, 0);
|
||||
if (player && player->player_id == (u8)_player_id) {
|
||||
if (player->callback) {
|
||||
player->callback(player->priv, STREAM_EVENT_START);
|
||||
}
|
||||
}
|
||||
os_mutex_post(&g_ring_mutex);
|
||||
break;
|
||||
case STREAM_EVENT_PREEMPTED:
|
||||
break;
|
||||
case STREAM_EVENT_NEGOTIATE_FAILD:
|
||||
case STREAM_EVENT_STOP:
|
||||
os_mutex_pend(&g_ring_mutex, 0);
|
||||
if (!player || player->player_id != (u8)_player_id) {
|
||||
os_mutex_post(&g_ring_mutex);
|
||||
break;
|
||||
}
|
||||
g_ring_player = NULL;
|
||||
jlstream_release(player->stream);
|
||||
os_mutex_post(&g_ring_mutex);
|
||||
|
||||
tone_player_free(player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ring_player_start(struct tone_player *player)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
if (g_ring_player) {
|
||||
goto __exit;
|
||||
}
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ring");
|
||||
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_RING);
|
||||
if (!player->stream) {
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
int player_id = player->player_id;
|
||||
jlstream_set_callback(player->stream, (void *)player_id, ring_player_callback);
|
||||
jlstream_set_scene(player->stream, player->scene);
|
||||
jlstream_set_coexist(player->stream, player->coexist);
|
||||
|
||||
if (player->callback) {
|
||||
err = player->callback(player->priv, STREAM_EVENT_INIT);
|
||||
if (err) {
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
jlstream_set_dec_file(player->stream, player, &tone_file_ops);
|
||||
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit;
|
||||
}
|
||||
g_ring_player = player;
|
||||
|
||||
return 0;
|
||||
|
||||
__exit:
|
||||
if (player->stream) {
|
||||
jlstream_release(player->stream);
|
||||
}
|
||||
|
||||
tone_player_free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __play_ring_file(const char *file_name, enum stream_coexist coexist)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
if (g_ring_player) {
|
||||
return -EBUSY;
|
||||
}
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
int err = tone_player_init(player, file_name);
|
||||
if (err) {
|
||||
tone_player_free(player);
|
||||
return err;
|
||||
}
|
||||
player->scene = STREAM_SCENE_RING;
|
||||
player->coexist = coexist;
|
||||
|
||||
return ring_player_start(player);
|
||||
}
|
||||
|
||||
int play_ring_file(const char *file_name)
|
||||
{
|
||||
return __play_ring_file(file_name, STREAM_COEXIST_AUTO);
|
||||
}
|
||||
|
||||
int play_ring_file_alone(const char *file_name)
|
||||
{
|
||||
return __play_ring_file(file_name, STREAM_COEXIST_DISABLE);
|
||||
}
|
||||
|
||||
static int __play_ring_file_with_calllback(const char *file_name, enum stream_coexist coexist, void *priv, tone_player_cb_t callback)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
if (g_ring_player) {
|
||||
return -EBUSY;
|
||||
}
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
int err = tone_player_init(player, file_name);
|
||||
if (err) {
|
||||
tone_player_free(player);
|
||||
return err;
|
||||
}
|
||||
player->priv = priv;
|
||||
player->callback = callback;
|
||||
player->scene = STREAM_SCENE_RING;
|
||||
player->coexist = coexist;
|
||||
|
||||
return ring_player_start(player);
|
||||
}
|
||||
|
||||
int play_ring_file_with_callback(const char *file_name, void *priv, tone_player_cb_t callback)
|
||||
{
|
||||
return __play_ring_file_with_calllback(file_name, STREAM_COEXIST_AUTO, priv, callback);
|
||||
}
|
||||
|
||||
int play_ring_file_alone_with_callback(const char *file_name, void *priv, tone_player_cb_t callback)
|
||||
{
|
||||
return __play_ring_file_with_calllback(file_name, STREAM_COEXIST_DISABLE, priv, callback);
|
||||
}
|
||||
|
||||
int ring_player_runing()
|
||||
{
|
||||
return g_ring_player ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
void ring_player_stop()
|
||||
{
|
||||
os_mutex_pend(&g_ring_mutex, 0);
|
||||
struct tone_player *player = g_ring_player;
|
||||
if (player) {
|
||||
if (player->stream) {
|
||||
jlstream_stop(player->stream, 50);
|
||||
jlstream_release(player->stream);
|
||||
}
|
||||
g_ring_player = NULL;
|
||||
}
|
||||
os_mutex_post(&g_ring_mutex);
|
||||
|
||||
if (player) {
|
||||
tone_player_free(player);
|
||||
}
|
||||
}
|
||||
|
||||
static int __ring_player_init()
|
||||
{
|
||||
os_mutex_create(&g_ring_mutex);
|
||||
return 0;
|
||||
}
|
||||
__initcall(__ring_player_init);
|
||||
|
||||
@@ -0,0 +1,637 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".tone_player.data.bss")
|
||||
#pragma data_seg(".tone_player.data")
|
||||
#pragma const_seg(".tone_player.text.const")
|
||||
#pragma code_seg(".tone_player.text")
|
||||
#endif
|
||||
#include "tone_player.h"
|
||||
#include "fs/resfile.h"
|
||||
#include "os/os_api.h"
|
||||
#include "system/init.h"
|
||||
#include "decoder_node.h"
|
||||
#include "jldemuxer.h"
|
||||
#include "app_config.h"
|
||||
|
||||
|
||||
extern const struct decoder_plug_ops decoder_plug_begin[];
|
||||
extern const struct decoder_plug_ops decoder_plug_end[];
|
||||
const struct stream_file_ops tone_file_ops;
|
||||
|
||||
static u8 g_player_id = 0;
|
||||
static OS_MUTEX g_tone_mutex;
|
||||
static struct list_head g_head = LIST_HEAD_INIT(g_head);
|
||||
|
||||
static int tone_player_start(struct tone_player *);
|
||||
static int tone_file_close(void *file);
|
||||
|
||||
__attribute__((weak))
|
||||
void tone_event_to_user(int event, u16 fname_uuid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void *open_next_file(struct tone_player *player)
|
||||
{
|
||||
if (player->next_file) {
|
||||
void *file = player->next_file;
|
||||
player->next_file = NULL;
|
||||
return file;
|
||||
}
|
||||
|
||||
int index = ++player->index;
|
||||
|
||||
do {
|
||||
if (player->file_name_list[index]) {
|
||||
char file_path[48];
|
||||
strcpy(file_path, FLASH_RES_PATH);
|
||||
strcpy(file_path + strlen(FLASH_RES_PATH), player->file_name_list[index]);
|
||||
void *file = resfile_open(file_path);
|
||||
if (file) {
|
||||
player->index = index;
|
||||
return file;
|
||||
}
|
||||
index++;
|
||||
} else {
|
||||
player->index = 0;
|
||||
break;
|
||||
}
|
||||
} while (index != player->index);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int tone_player_post_asyc_callback(tone_player_cb_t callback, void *cb_priv)
|
||||
{
|
||||
int msg[4];
|
||||
msg[0] = (int)callback;
|
||||
msg[1] = 2;
|
||||
msg[2] = (int)cb_priv;
|
||||
msg[3] = (int)STREAM_EVENT_STOP;
|
||||
return os_taskq_post_type("app_core", Q_CALLBACK, 4, msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void tone_player_free(struct tone_player *player)
|
||||
{
|
||||
int fname_uuid = player->fname_uuid;
|
||||
void *cb_priv = player->priv;
|
||||
tone_player_cb_t callback = player->callback;
|
||||
|
||||
if (--player->ref == 0) {
|
||||
tone_file_close(player);
|
||||
free(player);
|
||||
}
|
||||
if (callback) {
|
||||
/* callback(cb_priv, STREAM_EVENT_STOP); */
|
||||
tone_player_post_asyc_callback(callback, cb_priv);
|
||||
} else {
|
||||
tone_event_to_user(STREAM_EVENT_STOP, fname_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
static void tone_player_callback(void *_player_id, int event)
|
||||
{
|
||||
void *file = NULL;
|
||||
struct tone_player *player;
|
||||
|
||||
printf("tone_callback: %x, %d\n", event, (u8)_player_id);
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
os_mutex_pend(&g_tone_mutex, 0);
|
||||
if (list_empty(&g_head)) { //先判断是否为空防止触发异常
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
break;
|
||||
}
|
||||
player = list_first_entry(&g_head, struct tone_player, entry);
|
||||
if (player->player_id == (u8)_player_id) {
|
||||
if (player->callback) {
|
||||
player->callback(player->priv, STREAM_EVENT_START);
|
||||
}
|
||||
}
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
break;
|
||||
case STREAM_EVENT_PREEMPTED:
|
||||
case STREAM_EVENT_NEGOTIATE_FAILD:
|
||||
/*
|
||||
* 提示音被抢占或者参数协商失败,直接结束播放
|
||||
*/
|
||||
case STREAM_EVENT_STOP:
|
||||
|
||||
|
||||
os_mutex_pend(&g_tone_mutex, 0);
|
||||
if (list_empty(&g_head)) { //先判断是否为空防止触发异常
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
player = list_first_entry(&g_head, struct tone_player, entry);
|
||||
if (player->player_id != (u8)_player_id) {
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
printf("player_id_not_match: %d\n", player->player_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (event == STREAM_EVENT_STOP) {
|
||||
/*
|
||||
* 打开文件列表的下一个文件,重新启动解码
|
||||
*/
|
||||
while (1) {
|
||||
file = open_next_file(player);
|
||||
if (!file) {
|
||||
break;
|
||||
}
|
||||
resfile_close(player->file);
|
||||
player->file = file;
|
||||
int err = jlstream_start(player->stream);
|
||||
if (err == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
jlstream_release(player->stream);
|
||||
|
||||
list_del(&player->entry);
|
||||
if (!list_empty(&g_head)) {
|
||||
struct tone_player *p;
|
||||
p = list_first_entry(&g_head, struct tone_player, entry);
|
||||
tone_player_start(p);
|
||||
}
|
||||
|
||||
tone_player_free(player);
|
||||
}
|
||||
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int tone_file_read(void *p_file, u8 *buf, int len)
|
||||
{
|
||||
int offset = 0;
|
||||
struct tone_player *player = (struct tone_player *)p_file;
|
||||
|
||||
while (len) {
|
||||
if (!player->file) {
|
||||
break;
|
||||
}
|
||||
int rlen = resfile_read(player->file, buf + offset, len);
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
offset += rlen;
|
||||
if ((len -= rlen) == 0) {
|
||||
break;
|
||||
}
|
||||
if (player->scene == STREAM_SCENE_RING) {
|
||||
if (player->coding_type == AUDIO_CODING_WTGV2) {
|
||||
//WTS拼接提示音时,去掉头1byte
|
||||
resfile_seek(player->file, 1, RESFILE_SEEK_SET);
|
||||
} else {
|
||||
resfile_seek(player->file, 0, RESFILE_SEEK_SET);
|
||||
if (player->coding_type == AUDIO_CODING_MP3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (player->next_file) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* 打开文件列表中的下一个文件,检查format是否和当前文件相同
|
||||
* 如果相同就继读下一个文件, 可以保证TWS同步播放文件列表情况下的音频同步
|
||||
*/
|
||||
int index = player->index;
|
||||
void *file = open_next_file(player);
|
||||
if (!file) {
|
||||
player->index = index;
|
||||
break;
|
||||
}
|
||||
char name[16];
|
||||
resfile_get_name(file, name, 16);
|
||||
struct stream_file_ops file_ops = {
|
||||
.read = (int (*)(void *, u8 *, int))resfile_read,
|
||||
.seek = (int (*)(void *, int, int))resfile_seek,
|
||||
};
|
||||
struct stream_file_info file_info = {
|
||||
.file = file,
|
||||
.fname = name,
|
||||
.ops = &file_ops,
|
||||
};
|
||||
struct stream_fmt fmt;
|
||||
int err = jldemuxer_get_tone_file_fmt(&file_info, &fmt);
|
||||
if (err == 0) {
|
||||
if (player->coding_type == fmt.coding_type &&
|
||||
player->sample_rate == fmt.sample_rate &&
|
||||
player->channel_mode == fmt.channel_mode) {
|
||||
resfile_close(player->file);
|
||||
player->file = file;
|
||||
if (player->coding_type == AUDIO_CODING_WTGV2) {
|
||||
//WTS拼接提示音时,去掉头1byte
|
||||
resfile_seek(player->file, 1, RESFILE_SEEK_SET);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
player->next_file = file;
|
||||
break;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int tone_file_seek(void *file, int offset, int fromwhere)
|
||||
{
|
||||
struct tone_player *player = (struct tone_player *)file;
|
||||
|
||||
return resfile_seek(player->file, offset, fromwhere);
|
||||
}
|
||||
|
||||
static int tone_file_flen(void *file)
|
||||
{
|
||||
struct tone_player *player = (struct tone_player *)file;
|
||||
u32 len = 0;
|
||||
if (player->file) {
|
||||
len = resfile_get_len(player->file);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int tone_file_close(void *file)
|
||||
{
|
||||
struct tone_player *player = (struct tone_player *)file;
|
||||
|
||||
if (player->file) {
|
||||
resfile_close(player->file);
|
||||
player->file = NULL;
|
||||
}
|
||||
if (player->next_file) {
|
||||
resfile_close(player->next_file);
|
||||
player->next_file = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tone_file_get_fmt(void *file, struct stream_fmt *fmt)
|
||||
{
|
||||
struct tone_player *player = (struct tone_player *)file;
|
||||
|
||||
char name[16];
|
||||
resfile_get_name(player->file, name, 16);
|
||||
|
||||
struct stream_file_info file_info = {
|
||||
.file = player,
|
||||
.fname = name,
|
||||
.ops = &tone_file_ops,
|
||||
};
|
||||
int err = jldemuxer_get_tone_file_fmt(&file_info, fmt);
|
||||
if (err) {
|
||||
player->coding_type = AUDIO_CODING_UNKNOW;
|
||||
return err;
|
||||
}
|
||||
|
||||
player->coding_type = fmt->coding_type;
|
||||
player->sample_rate = fmt->sample_rate;
|
||||
player->channel_mode = fmt->channel_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct stream_file_ops tone_file_ops = {
|
||||
.read = tone_file_read,
|
||||
.seek = tone_file_seek,
|
||||
.close = tone_file_close,
|
||||
.get_fmt = tone_file_get_fmt,
|
||||
};
|
||||
|
||||
int tone_player_get_cur_time(struct tone_player *player)
|
||||
{
|
||||
os_mutex_pend(&g_tone_mutex, 0);
|
||||
|
||||
if (list_empty(&(g_head))) { //先判断是否为空
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
return -1;
|
||||
}
|
||||
if (!player) {
|
||||
player = list_first_entry(&g_head, struct tone_player, entry);
|
||||
}
|
||||
if (player && player->stream) {
|
||||
int ret = jlstream_node_ioctl(player->stream, NODE_UUID_DECODER, NODE_IOC_GET_CUR_TIME, 0);
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
return ret;
|
||||
}
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tone_player_get_total_time(struct tone_player *player)
|
||||
{
|
||||
os_mutex_pend(&g_tone_mutex, 0);
|
||||
|
||||
if (list_empty(&(g_head))) { //先判断是否为空
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
return -1;
|
||||
}
|
||||
if (!player) {
|
||||
player = list_first_entry(&g_head, struct tone_player, entry);
|
||||
}
|
||||
if (player && player->stream) {
|
||||
int ret = jlstream_node_ioctl(player->stream, NODE_UUID_DECODER, NODE_IOC_GET_TOTAL_TIME, 0);
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
return ret;
|
||||
}
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int tone_player_start(struct tone_player *player)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"tone");
|
||||
|
||||
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_TONE);
|
||||
if (!player->stream) {
|
||||
goto __exit0;
|
||||
}
|
||||
int player_id = player->player_id;
|
||||
jlstream_set_callback(player->stream, (void *)player_id, tone_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_FILE_LEN, (int)tone_file_flen(player));
|
||||
|
||||
if (player->callback) {
|
||||
err = player->callback(player->priv, STREAM_EVENT_INIT);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
}
|
||||
jlstream_set_dec_file(player->stream, player, &tone_file_ops);
|
||||
|
||||
err = jlstream_start(player->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(player->stream);
|
||||
__exit0:
|
||||
list_del(&player->entry);
|
||||
tone_player_free(player);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int tone_player_init(struct tone_player *player, const char *file_name)
|
||||
{
|
||||
void *file = NULL;
|
||||
int fname_uuid = 0;
|
||||
|
||||
player->ref = 1;
|
||||
if (file_name) {
|
||||
char file_path[64];
|
||||
strcpy(file_path, FLASH_RES_PATH);
|
||||
strcpy(file_path + strlen(FLASH_RES_PATH), file_name);
|
||||
file = resfile_open(file_path);
|
||||
if (!file) {
|
||||
printf("tone_player_faild: %s\n", file_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
fname_uuid = JBHash((u8 *)file_name, strlen(file_name));
|
||||
printf("tone_player: %s\n", file_name);
|
||||
}
|
||||
player->file = file;
|
||||
player->scene = STREAM_SCENE_TONE;
|
||||
player->player_id = g_player_id++;
|
||||
player->fname_uuid = fname_uuid;
|
||||
player->coexist = STREAM_COEXIST_AUTO;
|
||||
INIT_LIST_HEAD(&player->entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tone_player *tone_player_create(const char *file_name)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int err = tone_player_init(player, file_name);
|
||||
if (err) {
|
||||
tone_player_free(player);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
int tone_player_add(struct tone_player *player)
|
||||
{
|
||||
os_mutex_pend(&g_tone_mutex, 0);
|
||||
|
||||
if (list_empty(&g_head)) {
|
||||
int err = tone_player_start(player);
|
||||
if (err) {
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
list_add_tail(&player->entry, &g_head);
|
||||
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int play_tone_file(const char *file_name)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_player_create(file_name);
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
int play_tone_file_callback(const char *file_name, void *priv, tone_player_cb_t callback)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_player_create(file_name);
|
||||
if (!player) {
|
||||
if (callback) {
|
||||
callback(priv, STREAM_EVENT_STOP);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
player->priv = priv;
|
||||
player->callback = callback;
|
||||
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
static struct tone_player *tone_files_create(const char *const file_name[], u8 file_num)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
if (file_num > MAX_FILE_NUM) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
player = tone_player_create(file_name[0]);
|
||||
if (!player) {
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < file_num; i++) {
|
||||
player->file_name_list[i] = file_name[i];
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
int play_tone_files(const char *const file_name[], u8 file_num)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_files_create(file_name, file_num);
|
||||
if (!player) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
int play_tone_files_alone(const char *const file_name[], u8 file_num)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_files_create(file_name, file_num);
|
||||
if (!player) {
|
||||
return -EFAULT;
|
||||
}
|
||||
player->coexist = STREAM_COEXIST_DISABLE;
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
int play_tone_files_callback(const char *const file_name[], u8 file_num,
|
||||
void *priv, tone_player_cb_t callback)
|
||||
{
|
||||
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_files_create(file_name, file_num);
|
||||
if (!player) {
|
||||
if (callback) {
|
||||
callback(priv, STREAM_EVENT_STOP);
|
||||
}
|
||||
return -EFAULT;
|
||||
}
|
||||
player->priv = priv;
|
||||
player->callback = callback;
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
int play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
|
||||
void *priv, tone_player_cb_t callback)
|
||||
{
|
||||
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_files_create(file_name, file_num);
|
||||
if (!player) {
|
||||
if (callback) {
|
||||
callback(priv, STREAM_EVENT_STOP);
|
||||
}
|
||||
return -EFAULT;
|
||||
}
|
||||
player->priv = priv;
|
||||
player->callback = callback;
|
||||
player->coexist = STREAM_COEXIST_DISABLE;
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
int play_tone_file_alone(const char *file_name)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_player_create(file_name);
|
||||
if (!player) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
player->coexist = STREAM_COEXIST_DISABLE;
|
||||
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
|
||||
int play_tone_file_alone_callback(const char *file_name, void *priv,
|
||||
tone_player_cb_t callback)
|
||||
{
|
||||
struct tone_player *player;
|
||||
|
||||
player = tone_player_create(file_name);
|
||||
if (!player) {
|
||||
callback(priv, STREAM_EVENT_STOP);
|
||||
return -ENOMEM;
|
||||
}
|
||||
player->coexist = STREAM_COEXIST_DISABLE;
|
||||
player->priv = priv;
|
||||
player->callback = callback;
|
||||
|
||||
return tone_player_add(player);
|
||||
}
|
||||
|
||||
int tone_player_runing()
|
||||
{
|
||||
local_irq_disable();
|
||||
int ret = list_empty(&g_head) ? 0 : 1;
|
||||
local_irq_enable();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tone_player_stop()
|
||||
{
|
||||
struct tone_player *player, *n;
|
||||
|
||||
os_mutex_pend(&g_tone_mutex, 0);
|
||||
|
||||
list_for_each_entry_safe(player, n, &g_head, entry) {
|
||||
__list_del_entry(&player->entry);
|
||||
if (player->stream) {
|
||||
jlstream_stop(player->stream, 50);
|
||||
jlstream_release(player->stream);
|
||||
}
|
||||
tone_player_free(player);
|
||||
}
|
||||
|
||||
os_mutex_post(&g_tone_mutex);
|
||||
}
|
||||
|
||||
u16 tone_player_get_fname_uuid(const char *fname)
|
||||
{
|
||||
return JBHash((u8 *)fname, strlen(fname));
|
||||
}
|
||||
|
||||
|
||||
static int __tone_player_init()
|
||||
{
|
||||
os_mutex_create(&g_tone_mutex);
|
||||
return 0;
|
||||
}
|
||||
__initcall(__tone_player_init);
|
||||
|
||||
|
||||
@@ -0,0 +1,426 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".tws_tone_player.data.bss")
|
||||
#pragma data_seg(".tws_tone_player.data")
|
||||
#pragma const_seg(".tws_tone_player.text.const")
|
||||
#pragma code_seg(".tws_tone_player.text")
|
||||
#endif
|
||||
#include "tws_tone_player.h"
|
||||
#include "os/os_api.h"
|
||||
#include "system/init.h"
|
||||
#include "system/timer.h"
|
||||
#include "fs/resfile.h"
|
||||
#include "sync/audio_syncts.h"
|
||||
#include "media/bt_audio_timestamp.h"
|
||||
#include "reference_time.h"
|
||||
#include "classic/tws_api.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_USER_TWS_ENABLE
|
||||
|
||||
#define MAX_FNAME_LEN 32
|
||||
|
||||
struct tws_tone_message {
|
||||
enum stream_scene scene;
|
||||
enum stream_coexist coexist;
|
||||
u8 file_num;
|
||||
u8 network;
|
||||
u8 reference_clk;
|
||||
u8 net_addr[6];
|
||||
u32 timestamp;
|
||||
u32 tws_timestamp;
|
||||
u32 func_uuid;
|
||||
char name[MAX_FILE_NUM][MAX_FNAME_LEN];
|
||||
};
|
||||
|
||||
struct tws_tone_file {
|
||||
enum stream_scene scene;
|
||||
enum stream_coexist coexist;
|
||||
u16 delay_time;
|
||||
u32 func_uuid;
|
||||
char name[MAX_FNAME_LEN];
|
||||
};
|
||||
|
||||
|
||||
struct tws_tone_player {
|
||||
struct tone_player player;
|
||||
u8 reference;
|
||||
u8 network;
|
||||
u8 net_addr[6];
|
||||
u32 timestamp;
|
||||
u32 tws_timestamp;
|
||||
u32 func_uuid;
|
||||
char file_list[MAX_FILE_NUM][MAX_FNAME_LEN];
|
||||
};
|
||||
|
||||
static u8 g_tws_tone_adding = 0;
|
||||
|
||||
static void tws_tone_reference_clock_close(u8 id);
|
||||
static void tws_play_tone_try_timeout(void *arg);
|
||||
extern int ring_player_start(struct tone_player *player);
|
||||
|
||||
static int tws_player_callback(int fname_uuid, u32 func_uuid, enum stream_event event)
|
||||
{
|
||||
const struct tws_tone_callback *p;
|
||||
|
||||
for (p = tws_tone_cb_begin; p < tws_tone_cb_end; p++) {
|
||||
if (p->func_uuid == func_uuid) {
|
||||
if (p->callback) {
|
||||
p->callback(fname_uuid, event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tws_files_callback(void *priv, enum stream_event event)
|
||||
{
|
||||
return tws_player_callback(0, (u32)priv, event);
|
||||
}
|
||||
|
||||
static void play_timestamp_init(struct tws_tone_player *player)
|
||||
{
|
||||
if (!player->timestamp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->reference) {
|
||||
player->reference = audio_reference_clock_select(player->net_addr,
|
||||
player->network);
|
||||
if (!player->reference) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!audio_reference_network_exist(player->reference) && player->network == 0) {
|
||||
audio_reference_clock_exit(player->reference);
|
||||
player->network = 1;
|
||||
player->reference = audio_reference_clock_select(NULL, player->network);
|
||||
player->timestamp = player->tws_timestamp;
|
||||
}
|
||||
|
||||
u8 current_network = audio_reference_clock_network(NULL);
|
||||
if (current_network != (u8) - 1 && player->network != current_network) {
|
||||
audio_reference_clock_exit(player->reference);
|
||||
player->timestamp = audio_reference_clock_remapping(player->network,
|
||||
current_network, player->timestamp);
|
||||
current_network = audio_reference_clock_network(player->net_addr);
|
||||
player->reference = audio_reference_clock_select(current_network == 0 ?
|
||||
player->net_addr : NULL, current_network);
|
||||
}
|
||||
|
||||
if (player->timestamp && player->timestamp != (u32) - 1) {
|
||||
jlstream_node_ioctl(player->player.stream, NODE_UUID_DECODER,
|
||||
NODE_IOC_SET_TIME_STAMP, player->timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
static int tws_tone_player_callback(void *_player, enum stream_event event)
|
||||
{
|
||||
int err = 0;
|
||||
struct tws_tone_player *player = (struct tws_tone_player *)_player;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_INIT:
|
||||
play_timestamp_init(player);
|
||||
break;
|
||||
case STREAM_EVENT_START:
|
||||
if (player->func_uuid) {
|
||||
tws_player_callback(player->player.fname_uuid, player->func_uuid, event);
|
||||
}
|
||||
break;
|
||||
case STREAM_EVENT_STOP:
|
||||
if (player->reference) {
|
||||
tws_tone_reference_clock_close(player->reference);
|
||||
}
|
||||
int func_uuid = player->func_uuid;
|
||||
int fname_uuid = player->player.fname_uuid;
|
||||
free(player);
|
||||
if (func_uuid) {
|
||||
tws_player_callback(fname_uuid, func_uuid, event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void tws_tone_player_add_timeout(void *arg)
|
||||
{
|
||||
struct tws_tone_player *player = (struct tws_tone_player *)arg;
|
||||
|
||||
int offset = 30 * 1000 / 625;
|
||||
player->timestamp += offset;
|
||||
player->tws_timestamp += offset;
|
||||
|
||||
if (!tone_player_runing()) {
|
||||
tone_player_add(&player->player);
|
||||
g_tws_tone_adding = 0;
|
||||
} else {
|
||||
sys_timeout_add((void *)player, tws_tone_player_add_timeout, 30);
|
||||
}
|
||||
}
|
||||
|
||||
static void tws_tone_play_in_task(struct tws_tone_message *msg)
|
||||
{
|
||||
struct tws_tone_player *player;
|
||||
const char *file_name = msg->name[0];
|
||||
|
||||
printf("tws_tone_play: %x, %s\n", msg->timestamp, file_name);
|
||||
|
||||
player = zalloc(sizeof(*player));
|
||||
if (!player) {
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < msg->file_num; i++) {
|
||||
strcpy(player->file_list[i], msg->name[i]);
|
||||
player->player.file_name_list[i] = player->file_list[i];
|
||||
}
|
||||
|
||||
int err = tone_player_init(&player->player, player->file_list[0]);
|
||||
if (err) {
|
||||
free(player);
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
player->player.ref = 2;
|
||||
player->player.priv = player;
|
||||
player->player.callback = tws_tone_player_callback;
|
||||
player->player.scene = msg->scene;
|
||||
player->player.coexist = msg->coexist;
|
||||
|
||||
player->func_uuid = msg->func_uuid;
|
||||
player->timestamp = msg->timestamp;
|
||||
player->tws_timestamp = msg->tws_timestamp;
|
||||
player->network = msg->network;
|
||||
player->reference = msg->reference_clk;
|
||||
memcpy(player->net_addr, msg->net_addr, 6);
|
||||
|
||||
if (msg->scene == STREAM_SCENE_RING) {
|
||||
ring_player_start(&player->player);
|
||||
} else {
|
||||
if (!tone_player_runing()) {
|
||||
tone_player_add(&player->player);
|
||||
g_tws_tone_adding = 0;
|
||||
} else {
|
||||
sys_timeout_add((void *)player, tws_tone_player_add_timeout, 30);
|
||||
}
|
||||
}
|
||||
goto __exit1;
|
||||
|
||||
__exit0:
|
||||
g_tws_tone_adding = 0;
|
||||
tws_tone_reference_clock_close(msg->reference_clk);
|
||||
__exit1:
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static void tws_tone_file_data_in_irq(void *data, u16 len, bool rx)
|
||||
{
|
||||
int msg[4];
|
||||
|
||||
u8 *buf = malloc(len);
|
||||
if (!buf) {
|
||||
goto __err;
|
||||
}
|
||||
memcpy(buf, data, len);
|
||||
|
||||
msg[0] = (int)tws_tone_play_in_task;
|
||||
msg[1] = 1;
|
||||
msg[2] = (int)buf;
|
||||
|
||||
if (rx) {
|
||||
((struct tws_tone_message *)buf)->reference_clk = 0;
|
||||
}
|
||||
|
||||
int err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
|
||||
if (err == OS_ERR_NONE) {
|
||||
return;
|
||||
}
|
||||
if (buf) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
if (rx) {
|
||||
return;
|
||||
}
|
||||
|
||||
__err:
|
||||
g_tws_tone_adding = 0;
|
||||
struct tws_tone_message *tmsg = (struct tws_tone_message *)data;
|
||||
tws_tone_reference_clock_close(tmsg->reference_clk);
|
||||
}
|
||||
|
||||
REGISTER_TWS_FUNC_STUB(tws_tone_player_stub) = {
|
||||
.func_id = 0xE70A68F2,
|
||||
.func = tws_tone_file_data_in_irq,
|
||||
};
|
||||
|
||||
static void tws_tone_reference_clock_setup(struct tws_tone_message *msg)
|
||||
{
|
||||
msg->reference_clk = audio_reference_clock_select(NULL, 1);
|
||||
msg->network = audio_reference_clock_network(msg->net_addr);
|
||||
}
|
||||
|
||||
static void tws_tone_reference_clock_close(u8 id)
|
||||
{
|
||||
audio_reference_clock_exit(id);
|
||||
}
|
||||
|
||||
static int __tws_play_tone_file(const char *const file_list[], u8 file_num,
|
||||
int delay_msec, enum stream_scene scene,
|
||||
enum stream_coexist coexist,
|
||||
u32 func_uuid)
|
||||
{
|
||||
struct tws_tone_message msg;
|
||||
|
||||
if (tws_api_is_sniff_state()) {
|
||||
tws_api_tx_unsniff_req();
|
||||
delay_msec += 1000;
|
||||
}
|
||||
|
||||
if (scene == STREAM_SCENE_TONE &&
|
||||
(tone_player_runing() || g_tws_tone_adding)) {
|
||||
struct tws_tone_file *file = zalloc(sizeof(*file));
|
||||
if (file) {
|
||||
strcpy(file->name, file_list[0]);
|
||||
file->delay_time = delay_msec;
|
||||
file->scene = scene;
|
||||
file->coexist = coexist;
|
||||
file->func_uuid = func_uuid;
|
||||
sys_timeout_add((void *)file, tws_play_tone_try_timeout, 200);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int slot = (delay_msec + 1) * 1000 / 625;
|
||||
|
||||
tws_tone_reference_clock_setup(&msg);
|
||||
msg.timestamp = audio_reference_clock_time() + slot;
|
||||
msg.tws_timestamp = audio_reference_network_clock_time(1) + slot;
|
||||
msg.scene = scene;
|
||||
msg.coexist = coexist;
|
||||
msg.func_uuid = func_uuid;
|
||||
msg.file_num = file_num;
|
||||
|
||||
for (int i = 0; i < file_num; i++) {
|
||||
strcpy(msg.name[i], file_list[i]);
|
||||
}
|
||||
int data_len = offsetof(struct tws_tone_message, name) + file_num * MAX_FNAME_LEN;
|
||||
|
||||
printf("tws_play_tone_file: %x, %s, %d\n", msg.network, file_list[0], data_len);
|
||||
|
||||
int err = tws_api_send_data_to_sibling(&msg, data_len, 0xE70A68F2);
|
||||
|
||||
if (scene == STREAM_SCENE_TONE) {
|
||||
g_tws_tone_adding = err == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
tws_tone_reference_clock_close(msg.reference_clk);
|
||||
|
||||
if (scene == STREAM_SCENE_RING) {
|
||||
err = play_ring_file(file_list[0]);
|
||||
} else {
|
||||
if (coexist == STREAM_COEXIST_AUTO) {
|
||||
err = play_tone_files_callback(file_list, file_num, (void *)func_uuid,
|
||||
tws_files_callback);
|
||||
} else {
|
||||
if (file_num == 1) {
|
||||
err = play_tone_file_alone_callback(file_list[0], (void *)func_uuid,
|
||||
tws_files_callback);
|
||||
} else {
|
||||
err = play_tone_files_callback(file_list, file_num, (void *)func_uuid,
|
||||
tws_files_callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tws_play_tone_try_timeout(void *arg)
|
||||
{
|
||||
struct tws_tone_file *file = (struct tws_tone_file *)arg;
|
||||
if (file) {
|
||||
const char *fname = file->name;
|
||||
__tws_play_tone_file(&fname, 1, file->delay_time,
|
||||
file->scene, file->coexist, file->func_uuid);
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
|
||||
int tws_play_tone_file(const char *file_name, int delay_msec)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
|
||||
STREAM_COEXIST_AUTO, 0);
|
||||
}
|
||||
|
||||
int tws_play_tone_file_callback(const char *file_name, int delay_msec, u32 func_uuid)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
|
||||
STREAM_COEXIST_AUTO, func_uuid);
|
||||
}
|
||||
|
||||
int tws_play_ring_file(const char *file_name, int delay_msec)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
|
||||
STREAM_COEXIST_AUTO, 0);
|
||||
}
|
||||
|
||||
int tws_play_ring_file_alone(const char *file_name, int delay_msec)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
|
||||
STREAM_COEXIST_DISABLE, 0);
|
||||
}
|
||||
|
||||
int tws_play_ring_file_callback(const char *file_name, int delay_msec, u32 func_uuid)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
|
||||
STREAM_COEXIST_AUTO, func_uuid);
|
||||
}
|
||||
|
||||
int tws_play_ring_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
|
||||
STREAM_COEXIST_DISABLE, func_uuid);
|
||||
}
|
||||
|
||||
int tws_play_tone_files_callback(const char *const file_name[], u8 file_num,
|
||||
int delay_msec, u32 func_uuid)
|
||||
{
|
||||
return __tws_play_tone_file(file_name, file_num, delay_msec, STREAM_SCENE_TONE,
|
||||
STREAM_COEXIST_AUTO, func_uuid);
|
||||
}
|
||||
|
||||
int tws_play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
|
||||
int delay_msec, u32 func_uuid)
|
||||
{
|
||||
return __tws_play_tone_file(file_name, file_num, delay_msec, STREAM_SCENE_TONE,
|
||||
STREAM_COEXIST_DISABLE, func_uuid);
|
||||
}
|
||||
|
||||
int tws_play_tone_file_alone(const char *file_name, int delay_msec)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
|
||||
STREAM_COEXIST_DISABLE, 0);
|
||||
}
|
||||
|
||||
int tws_play_tone_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid)
|
||||
{
|
||||
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
|
||||
STREAM_COEXIST_DISABLE, func_uuid);
|
||||
}
|
||||
|
||||
|
||||
static int tws_tone_player_init()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
__initcall(tws_tone_player_init);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,196 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".ai_voice_recoder.data.bss")
|
||||
#pragma data_seg(".ai_voice_recoder.data")
|
||||
#pragma const_seg(".ai_voice_recoder.text.const")
|
||||
#pragma code_seg(".ai_voice_recoder.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "system/includes.h"
|
||||
#include "ai_voice_recoder.h"
|
||||
#include "encoder_node.h"
|
||||
#include "asm/dac.h"
|
||||
#include "audio_cvp.h"
|
||||
|
||||
#if TCFG_AI_VOICE_ENABLE
|
||||
struct ai_voice_recoder {
|
||||
struct jlstream *stream;
|
||||
};
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
|
||||
static struct ai_voice_recoder *g_ai_voice_recoder = NULL;
|
||||
|
||||
|
||||
static void ai_voice_recoder_callback(void *private_data, int event)
|
||||
{
|
||||
struct ai_voice_recoder *recoder = g_ai_voice_recoder;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ai_voice_recoder_set_ai_tx_node_func(int (*func)(u8 *, u32))
|
||||
{
|
||||
struct ai_voice_recoder *recoder = g_ai_voice_recoder;
|
||||
if (recoder && recoder->stream) {
|
||||
jlstream_node_ioctl(recoder->stream, NODE_UUID_AI_TX, NODE_IOC_SET_PRIV_FMT, (int)func);
|
||||
}
|
||||
}
|
||||
|
||||
int ai_voice_recoder_open(u32 code_type, u8 ai_type)
|
||||
{
|
||||
int err;
|
||||
struct stream_fmt fmt;
|
||||
struct encoder_fmt enc_fmt;
|
||||
struct ai_voice_recoder *recoder;
|
||||
u16 source_uuid = 0;
|
||||
|
||||
if (g_ai_voice_recoder) {
|
||||
return -EBUSY;
|
||||
}
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_voice");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
recoder = malloc(sizeof(*recoder));
|
||||
if (!recoder) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
|
||||
if (!recoder->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
switch (code_type) {
|
||||
case AUDIO_CODING_OPUS:
|
||||
// bitrate
|
||||
// 16000,32000,64000 这三个码率分别对应非ogg解码库
|
||||
// 的 OPUS_SRINDEX 值为0,1,2
|
||||
// format
|
||||
// 0:百度_无头.
|
||||
// 1:酷狗_eng+range.
|
||||
// 2:ogg封装,pc软件可播放.
|
||||
// 3:size+rangeFinal. 源码可兼容版本.
|
||||
// complexity
|
||||
// 0|1|2|3 3质量最好.速度要求最高.
|
||||
// frame_ms (由frame_dms / 10得出)
|
||||
// 20|40|60|80|100 ms.
|
||||
// sample_rate
|
||||
// sample_rate=16k ignore
|
||||
//
|
||||
// 注意
|
||||
// 1. struct encoder_fmt是配置编码器私有参数
|
||||
// 有效的参数:
|
||||
// complexity, format, frame_dms
|
||||
// 不起效的参数:
|
||||
// bit_rate, sample_rate, ch_num, bit_width
|
||||
// 不起效参数只用作阅读,需要修改请到音频流程图的”编码器“节点修改
|
||||
enc_fmt.bit_rate = 16000;
|
||||
enc_fmt.complexity = 0;
|
||||
enc_fmt.sample_rate = 16000;
|
||||
/* enc_fmt.format = (ai_type >> 6); //传入的ai_type实参是bit7:6,用于选择封装格式,兼容以前调用的接口 */
|
||||
enc_fmt.format = (ai_type); //传入的ai_type实参是bit7:6,用于选择封装格式,兼容以前调用的接口
|
||||
printf("[msg]%s-%d>>>>>>>>>>>enc_fmt.format=%d", __FUNCTION__, __LINE__, enc_fmt.format);
|
||||
enc_fmt.frame_dms = 20 * 10;//与工具保持一致,要乘以10,表示20ms
|
||||
fmt.coding_type = AUDIO_CODING_OPUS;
|
||||
fmt.sample_rate = 16000;
|
||||
fmt.bit_rate = 16000;
|
||||
fmt.channel_mode = AUDIO_CH_MIX;
|
||||
break;
|
||||
case AUDIO_CODING_SPEEX:
|
||||
enc_fmt.quality = 5;
|
||||
enc_fmt.complexity = 2;
|
||||
enc_fmt.sample_rate = 16000;
|
||||
fmt.sample_rate = 16000;
|
||||
fmt.coding_type = AUDIO_CODING_SPEEX;
|
||||
break;
|
||||
case AUDIO_CODING_PCM:
|
||||
fmt.sample_rate = 16000;
|
||||
fmt.coding_type = AUDIO_CODING_PCM;
|
||||
break;
|
||||
default:
|
||||
printf("do not support this type !!!\n");
|
||||
err = -ENOMEM;
|
||||
goto __exit1;
|
||||
break;
|
||||
}
|
||||
printf("coding_type %x", code_type);
|
||||
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_PRIV_FMT, (int)(&enc_fmt));
|
||||
err += jlstream_node_ioctl(recoder->stream, NODE_UUID_AI_TX, NODE_IOC_SET_FMT, (int)(&fmt));
|
||||
|
||||
//设置ADC的中断点数
|
||||
if (code_type == AUDIO_CODING_PCM) {
|
||||
err += jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 80);
|
||||
} else {
|
||||
err += jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 320);
|
||||
}
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
u16 node_uuid = get_cvp_node_uuid();
|
||||
u32 ref_sr = audio_dac_get_sample_rate(&dac_hdl);
|
||||
if (node_uuid) {
|
||||
#if !(TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE))
|
||||
#if (TCFG_ESCO_DL_CVSD_SR_USE_16K > 1)
|
||||
jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_PRIV_FMT, source_uuid);
|
||||
if (err && (err != -ENOENT)) { //兼容没有cvp节点的情况
|
||||
goto __exit1;
|
||||
}
|
||||
jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256);
|
||||
|
||||
|
||||
}
|
||||
jlstream_set_callback(recoder->stream, recoder->stream, ai_voice_recoder_callback);
|
||||
jlstream_set_scene(recoder->stream, STREAM_SCENE_AI_VOICE);
|
||||
err = jlstream_start(recoder->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
printf("ai voice recoder open succ\n");
|
||||
|
||||
g_ai_voice_recoder = recoder;
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(recoder->stream);
|
||||
__exit0:
|
||||
free(recoder);
|
||||
return err;
|
||||
}
|
||||
|
||||
void ai_voice_recoder_close()
|
||||
{
|
||||
struct ai_voice_recoder *recoder = g_ai_voice_recoder;
|
||||
|
||||
if (!recoder) {
|
||||
return;
|
||||
}
|
||||
jlstream_stop(recoder->stream, 0);
|
||||
jlstream_release(recoder->stream);
|
||||
|
||||
free(recoder);
|
||||
g_ai_voice_recoder = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"ai_voice");
|
||||
}
|
||||
|
||||
|
||||
static u8 ai_voice_record_idle_query(void)
|
||||
{
|
||||
return g_ai_voice_recoder ? 0 : 1;
|
||||
}
|
||||
|
||||
REGISTER_LP_TARGET(ai_voice_record_lp_target) = {
|
||||
.name = "ai_voice",
|
||||
.is_idle = ai_voice_record_idle_query,
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".dev_flow_recoder.data.bss")
|
||||
#pragma data_seg(".dev_flow_recoder.data")
|
||||
#pragma const_seg(".dev_flow_recoder.text.const")
|
||||
#pragma code_seg(".dev_flow_recoder.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "dev_flow_recoder.h"
|
||||
|
||||
struct dev_flow_recoder {
|
||||
struct jlstream *stream;
|
||||
};
|
||||
|
||||
static struct dev_flow_recoder *g_dev_flow_recoder = NULL;
|
||||
|
||||
|
||||
static void dev_flow_recoder_callback(void *private_data, int event)
|
||||
{
|
||||
struct dev_flow_recoder *recoder = g_dev_flow_recoder;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//自定义数据流recoder 启动
|
||||
int dev_flow_recoder_open(void)
|
||||
{
|
||||
int err = 0;
|
||||
struct dev_flow_recoder *recoder;
|
||||
|
||||
if (g_dev_flow_recoder) {
|
||||
return -EBUSY;
|
||||
}
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"dev_flow");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
recoder = malloc(sizeof(*recoder));
|
||||
if (!recoder) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
导入自定义音频流的源节点UUID,如下ADC节点为NODE_UUID_ADC,
|
||||
若是其他源节点,需使用对应节点的UUID
|
||||
*/
|
||||
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
|
||||
if (!recoder->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
/*-----以下用于设置当前数据对应节点的特性-----*/
|
||||
|
||||
//设置当前数据流-自定义输出节点的参数
|
||||
/* struct stream_fmt fmt = {0}; */
|
||||
/* err = jlstream_node_ioctl(recoder->stream, NODE_UUID_SINK_DEV, NODE_IOC_SET_FMT, (int)(&fmt)); */
|
||||
//设置当前数据流-ADC的中断点数
|
||||
/* err += jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256); */
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
jlstream_set_callback(recoder->stream, recoder->stream, dev_flow_recoder_callback);
|
||||
jlstream_set_scene(recoder->stream, STREAM_SCENE_DEV_FLOW);
|
||||
err = jlstream_start(recoder->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
g_dev_flow_recoder = recoder;
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(recoder->stream);
|
||||
__exit0:
|
||||
free(recoder);
|
||||
return err;
|
||||
}
|
||||
|
||||
//自定义数据流recoder 查询是否活动
|
||||
bool dev_flow_recoder_runing(void)
|
||||
{
|
||||
return g_dev_flow_recoder != NULL;
|
||||
}
|
||||
|
||||
//自定义数据流recoder 关闭
|
||||
void dev_flow_recoder_close(void)
|
||||
{
|
||||
struct dev_flow_recoder *recoder = g_dev_flow_recoder;
|
||||
|
||||
if (!recoder) {
|
||||
return;
|
||||
}
|
||||
jlstream_stop(recoder->stream, 0);
|
||||
jlstream_release(recoder->stream);
|
||||
|
||||
free(recoder);
|
||||
g_dev_flow_recoder = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"dev_flow");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".esco_recoder.data.bss")
|
||||
#pragma data_seg(".esco_recoder.data")
|
||||
#pragma const_seg(".esco_recoder.text.const")
|
||||
#pragma code_seg(".esco_recoder.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "esco_recoder.h"
|
||||
#include "encoder_node.h"
|
||||
#include "media/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_cvp.h"
|
||||
#include "esco_player.h"
|
||||
|
||||
|
||||
#if TCFG_AUDIO_DUT_ENABLE
|
||||
#include "audio_dut_control.h"
|
||||
#endif
|
||||
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
struct esco_recoder {
|
||||
struct jlstream *stream;
|
||||
};
|
||||
|
||||
static struct esco_recoder *g_esco_recoder = NULL;
|
||||
|
||||
|
||||
static void esco_recoder_callback(void *private_data, int event)
|
||||
{
|
||||
struct esco_recoder *recoder = g_esco_recoder;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int esco_recoder_open(u8 link_type, void *bt_addr)
|
||||
{
|
||||
int err;
|
||||
struct encoder_fmt enc_fmt;
|
||||
struct esco_recoder *recoder;
|
||||
u16 source_uuid = 0;
|
||||
|
||||
if (g_esco_recoder) {
|
||||
return -EBUSY;
|
||||
}
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"esco");
|
||||
if (uuid == 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
recoder = malloc(sizeof(*recoder));
|
||||
if (!recoder) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
|
||||
source_uuid = NODE_UUID_ADC;
|
||||
if (!recoder->stream) {
|
||||
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_PDM_MIC);
|
||||
source_uuid = NODE_UUID_PDM_MIC;
|
||||
}
|
||||
if (!recoder->stream) {
|
||||
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_IIS0_RX);
|
||||
source_uuid = NODE_UUID_IIS0_RX;
|
||||
}
|
||||
if (!recoder->stream) {
|
||||
err = -ENOMEM;
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
//设置ADC的中断点数
|
||||
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
jlstream_node_ioctl(recoder->stream, NODE_UUID_ESCO_TX, NODE_IOC_SET_BTADDR, (int)bt_addr);
|
||||
//设置源节点是哪个
|
||||
u16 node_uuid = get_cvp_node_uuid();
|
||||
u32 ref_sr = audio_dac_get_sample_rate(&dac_hdl);
|
||||
if (node_uuid) {
|
||||
#if !(TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE))
|
||||
#if (TCFG_ESCO_DL_CVSD_SR_USE_16K > 1)
|
||||
jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
|
||||
#endif
|
||||
#endif
|
||||
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_PRIV_FMT, source_uuid);
|
||||
if (err && (err != -ENOENT)) { //兼容没有cvp节点的情况
|
||||
goto __exit1;
|
||||
}
|
||||
}
|
||||
|
||||
if (link_type == JL_DOGLE_ACL) { //连接方式为ACL msbc 编码需要用软件; aec 参考采样率为48000;
|
||||
enc_fmt.sw_hw_option = 1; //连接方式时ACL msbc 编码需要用软件
|
||||
//设置编码参数
|
||||
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_PRIV_FMT, (int)(&enc_fmt));
|
||||
//根据回音消除的类型,将配置传递到对应的节点
|
||||
if (node_uuid) {
|
||||
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
|
||||
}
|
||||
} else {
|
||||
#if (defined CONFIG_CPU_BR35)
|
||||
enc_fmt.sw_hw_option = 1; //br35 msbc 编码需要用软件
|
||||
//设置编码参数
|
||||
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_PRIV_FMT, (int)(&enc_fmt));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (err && (err != -ENOENT)) { //兼容没有节点的情况
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
jlstream_set_callback(recoder->stream, recoder->stream, esco_recoder_callback);
|
||||
jlstream_set_scene(recoder->stream, STREAM_SCENE_ESCO);
|
||||
err = jlstream_start(recoder->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
g_esco_recoder = recoder;
|
||||
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(recoder->stream);
|
||||
__exit0:
|
||||
free(recoder);
|
||||
return err;
|
||||
}
|
||||
|
||||
void esco_recoder_close()
|
||||
{
|
||||
struct esco_recoder *recoder = g_esco_recoder;
|
||||
|
||||
if (!recoder) {
|
||||
return;
|
||||
}
|
||||
jlstream_stop(recoder->stream, 0);
|
||||
jlstream_release(recoder->stream);
|
||||
|
||||
free(recoder);
|
||||
g_esco_recoder = NULL;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"esco");
|
||||
#if TCFG_AUDIO_DUT_ENABLE
|
||||
//退出通话默认设置为算法模式
|
||||
cvp_dut_mode_set(CVP_DUT_MODE_ALGORITHM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern bool esco_player_runing();
|
||||
int esco_recoder_switch(u8 en)
|
||||
{
|
||||
if (!esco_player_runing()) {
|
||||
printf("esco player close now, non-operational!");
|
||||
return 1;
|
||||
}
|
||||
if (en) {
|
||||
//固定LINK_SCO类型,dongle不跑switch
|
||||
u8 bt_addr[6];
|
||||
esco_player_get_btaddr(bt_addr);
|
||||
esco_recoder_open(COMMON_SCO, bt_addr);
|
||||
} else {
|
||||
esco_recoder_close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//esco_recoder复位流程,目前提供产测使用
|
||||
int esco_recoder_reset(void)
|
||||
{
|
||||
if (!esco_player_runing()) {
|
||||
printf("esco player close now, non-operational!");
|
||||
return 1;
|
||||
}
|
||||
u8 bt_addr[6];
|
||||
//产测流程,固定LINK_SCO类型
|
||||
esco_recoder_close();
|
||||
esco_player_get_btaddr(bt_addr);
|
||||
esco_recoder_open(COMMON_SCO, bt_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".file_recorder.data.bss")
|
||||
#pragma data_seg(".file_recorder.data")
|
||||
#pragma const_seg(".file_recorder.text.const")
|
||||
#pragma code_seg(".file_recorder.text")
|
||||
#endif
|
||||
#include "file_recorder.h"
|
||||
#include "media/includes.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_APP_RECORD_EN || TCFG_MIX_RECORD_ENABLE
|
||||
|
||||
static struct list_head g_recorder_head = LIST_HEAD_INIT(g_recorder_head);
|
||||
|
||||
static void file_recorder_callback(void *private_data, int event)
|
||||
{
|
||||
struct file_recorder *recorder, *n;
|
||||
|
||||
printf("file_recorder_callback: %x \n", event);
|
||||
|
||||
list_for_each_entry_safe(recorder, n, &g_recorder_head, entry) {
|
||||
if (recorder->stream->id == (int)private_data) {
|
||||
if (recorder->callback) {
|
||||
recorder->callback(recorder->priv, event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct file_recorder *file_recorder_open(int pipeline_uuid, int snode_uuid)
|
||||
{
|
||||
struct file_recorder *recorder;
|
||||
struct jlstream *stream;
|
||||
|
||||
recorder = zalloc(sizeof(*recorder));
|
||||
if (!recorder) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream = jlstream_pipeline_parse(pipeline_uuid, snode_uuid);
|
||||
if (!stream) {
|
||||
free(recorder);
|
||||
return NULL;
|
||||
}
|
||||
recorder->stream = stream;
|
||||
|
||||
jlstream_node_ioctl(stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256);
|
||||
jlstream_set_scene(stream, STREAM_SCENE_RECODER);
|
||||
jlstream_add_thread(stream, NULL);
|
||||
|
||||
int id = stream->id;
|
||||
jlstream_set_callback(stream, (void *)id, file_recorder_callback);
|
||||
|
||||
list_add(&recorder->entry, &g_recorder_head);
|
||||
|
||||
return recorder;
|
||||
}
|
||||
|
||||
static int recorder_fread(void *_recorder, u8 *buf, int len)
|
||||
{
|
||||
struct file_recorder *recorder = (struct file_recorder *)_recorder;
|
||||
|
||||
if (!recorder->file) {
|
||||
return 0;
|
||||
}
|
||||
if (recorder->fops) {
|
||||
return recorder->fops->read(recorder->file, buf, len);
|
||||
}
|
||||
return fread(buf, len, 1, (FILE *)recorder->file);
|
||||
}
|
||||
|
||||
static int recorder_fseek(void *_recorder, int offset, int from)
|
||||
{
|
||||
struct file_recorder *recorder = (struct file_recorder *)_recorder;
|
||||
if (!recorder->file) {
|
||||
return 0;
|
||||
}
|
||||
if (recorder->fops) {
|
||||
return recorder->fops->seek(recorder->file, offset, from);
|
||||
}
|
||||
return fseek((FILE *)recorder->file, offset, from);
|
||||
}
|
||||
|
||||
static int recorder_fwrite(void *_recorder, u8 *buf, int len)
|
||||
{
|
||||
int wlen;
|
||||
struct file_recorder *recorder = (struct file_recorder *)_recorder;
|
||||
if (!recorder->file) {
|
||||
return 0;
|
||||
}
|
||||
if (recorder->fops) {
|
||||
wlen = recorder->fops->write(recorder->file, buf, len);
|
||||
} else {
|
||||
wlen = fwrite(buf, len, 1, (FILE *)recorder->file);
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
static int recorder_fclose(void *_recorder)
|
||||
{
|
||||
struct file_recorder *recorder = (struct file_recorder *)_recorder;
|
||||
if (!recorder->file) {
|
||||
return 0;
|
||||
}
|
||||
#if AUDIO_RECORD_CUT_HEAD_TAIL_EN
|
||||
int f_len = ftell((FILE *)recorder->file);
|
||||
if ((recorder->cut_tail_size) && ((f_len - recorder->head_size) > recorder->cut_tail_size)) {
|
||||
f_len -= recorder->cut_tail_size;
|
||||
fseek(recorder->file, f_len, SEEK_SET);
|
||||
}
|
||||
#endif
|
||||
if (recorder->fops) {
|
||||
if (!recorder->fops->close) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return recorder->fops->close(recorder->file);
|
||||
}
|
||||
return fclose((FILE *)recorder->file);
|
||||
}
|
||||
|
||||
static const struct stream_file_ops recorder_fops = {
|
||||
.read = recorder_fread,
|
||||
.seek = recorder_fseek,
|
||||
.write = recorder_fwrite,
|
||||
};
|
||||
|
||||
FILE *file_recorder_open_file(struct file_recorder *recorder, const char *fname)
|
||||
{
|
||||
recorder->file = fopen(fname, "w+");
|
||||
if (!recorder->file) {
|
||||
printf("open file %s faild\n", fname);
|
||||
return NULL;
|
||||
}
|
||||
jlstream_set_enc_file(recorder->stream, recorder, &recorder_fops);
|
||||
printf("open file %s suss\n", fname);
|
||||
|
||||
return (FILE *)recorder->file;
|
||||
}
|
||||
|
||||
int file_recorder_set_file(struct file_recorder *recorder, void *file,
|
||||
const struct stream_file_ops *fops)
|
||||
{
|
||||
recorder->file = file;
|
||||
recorder->fops = fops;
|
||||
jlstream_set_enc_file(recorder->stream, recorder, &recorder_fops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *file_recorder_change_file(struct file_recorder *recorder, void *new_file)
|
||||
{
|
||||
void *file = recorder->file;
|
||||
recorder->file = new_file;
|
||||
return file;
|
||||
}
|
||||
|
||||
int file_recorder_get_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt)
|
||||
{
|
||||
return jlstream_ioctl(recorder->stream, NODE_IOC_GET_ENC_FMT, (int)fmt);
|
||||
}
|
||||
|
||||
int file_recorder_set_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt)
|
||||
{
|
||||
return jlstream_ioctl(recorder->stream, NODE_IOC_SET_ENC_FMT, (int)fmt);
|
||||
}
|
||||
|
||||
void file_recorder_set_callback(struct file_recorder *recorder, void *priv,
|
||||
file_recorder_cb_t callback)
|
||||
{
|
||||
recorder->priv = priv;
|
||||
recorder->callback = callback;
|
||||
}
|
||||
|
||||
void file_recorder_seamless_set(struct file_recorder *recorder, struct seamless_recording *seamless)
|
||||
{
|
||||
jlstream_node_ioctl(recorder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_SEAMLESS, (int)seamless);
|
||||
}
|
||||
|
||||
int file_recorder_start(struct file_recorder *recorder)
|
||||
{
|
||||
int err = jlstream_start(recorder->stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
int file_recorder_stop(struct file_recorder *recorder, bool close_file)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!recorder) {
|
||||
return -EINVAL;
|
||||
}
|
||||
jlstream_stop(recorder->stream, 50);
|
||||
if (close_file) {
|
||||
err = recorder_fclose(recorder);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int file_recorder_release(struct file_recorder *recorder)
|
||||
{
|
||||
if (!recorder) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
jlstream_release(recorder->stream);
|
||||
list_del(&recorder->entry);
|
||||
free(recorder);
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"recorder");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_recorder_close(struct file_recorder *recorder, bool close_file)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!recorder) {
|
||||
return -EINVAL;
|
||||
}
|
||||
jlstream_stop(recorder->stream, 50);
|
||||
jlstream_release(recorder->stream);
|
||||
|
||||
if (close_file) {
|
||||
err = recorder_fclose(recorder);
|
||||
}
|
||||
|
||||
list_del(&recorder->entry);
|
||||
free(recorder);
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"recorder");
|
||||
return err;
|
||||
}
|
||||
|
||||
int file_recorder_get_enc_time(struct file_recorder *recorder)
|
||||
{
|
||||
int ret = 0;
|
||||
if (recorder && recorder->file) {
|
||||
ret = jlstream_node_ioctl(recorder->stream, NODE_UUID_ENCODER, NODE_IOC_GET_CUR_TIME, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".pc_mic_recoder.data.bss")
|
||||
#pragma data_seg(".pc_mic_recoder.data")
|
||||
#pragma const_seg(".pc_mic_recoder.text.const")
|
||||
#pragma code_seg(".pc_mic_recoder.text")
|
||||
#endif
|
||||
#include "pc_mic_recoder.h"
|
||||
#include "sdk_config.h"
|
||||
#include "media/includes.h"
|
||||
#include "jlstream.h"
|
||||
#include "uac_stream.h"
|
||||
#include "asm/dac.h"
|
||||
#include "audio_config_def.h"
|
||||
#include "app_config.h"
|
||||
#include "app_main.h"
|
||||
#include "volume_node.h"
|
||||
#include "audio_cvp.h"
|
||||
#include "pc_spk_player.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[pcmic]"
|
||||
#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_USB_SLAVE_AUDIO_MIC_ENABLE
|
||||
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
|
||||
typedef enum {
|
||||
PC_MIC_STA_CLOSE,
|
||||
PC_MIC_STA_WAIT_CLOSE,
|
||||
PC_MIC_STA_OPEN,
|
||||
PC_MIC_STA_WAIT_OPEN,
|
||||
} pc_mic_state_t;
|
||||
pc_mic_state_t g_pc_mic_state;
|
||||
|
||||
struct pc_mic_recoder {
|
||||
struct jlstream *stream;
|
||||
};
|
||||
static struct pc_mic_recoder *g_pc_mic_recoder = NULL;
|
||||
|
||||
static u8 pcmic_volume_wait_set_flag = 0;
|
||||
static u8 pcm_mic_recoder_check = 0;
|
||||
static OS_MUTEX mic_rec_mutex;
|
||||
static int pcm_mic_recoder_init(void)
|
||||
{
|
||||
os_mutex_create(&mic_rec_mutex);
|
||||
return 0;
|
||||
}
|
||||
__initcall(pcm_mic_recoder_init);
|
||||
|
||||
void pcm_mic_recoder_dump(int force_dump)
|
||||
{
|
||||
os_mutex_pend(&mic_rec_mutex, 0);
|
||||
struct pc_mic_recoder *recoder = g_pc_mic_recoder;
|
||||
if (recoder && recoder->stream) {
|
||||
jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_FORCE_DUMP_PACKET, force_dump);
|
||||
} else {
|
||||
pcm_mic_recoder_check = force_dump;
|
||||
}
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
}
|
||||
|
||||
static void pc_mic_recoder_callback(void *private_data, int event)
|
||||
{
|
||||
struct pc_mic_recoder *recoder = g_pc_mic_recoder;
|
||||
struct jlstream *stream = (struct jlstream *)private_data;
|
||||
u16 volume;
|
||||
struct volume_cfg cfg;
|
||||
int err;
|
||||
|
||||
switch (event) {
|
||||
case STREAM_EVENT_START:
|
||||
uac_mic_stream_get_volume(&volume);
|
||||
cfg.bypass = VOLUME_NODE_CMD_SET_VOL;
|
||||
cfg.cur_vol = volume;
|
||||
err = jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, "Vol_PcMic", (void *)&cfg, sizeof(struct volume_cfg));
|
||||
log_info(">>> pc mic vol: %d, ret:%d", volume, err);
|
||||
#if TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE)
|
||||
/*打开pc mic,没有开skp,忽略外部参考数据*/
|
||||
printf("STREAM_EVENT_START");
|
||||
if (!pc_spk_player_runing()) {
|
||||
printf("CVP_OUTWAY_REF_IGNORE, 1");
|
||||
audio_cvp_ioctl(CVP_OUTWAY_REF_IGNORE, 1, NULL);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int pc_mic_recoder_open(void)
|
||||
{
|
||||
os_mutex_pend(&mic_rec_mutex, 0);
|
||||
struct pc_mic_recoder *recoder = NULL;
|
||||
u16 source_uuid;
|
||||
if (g_pc_mic_recoder) {
|
||||
log_error("## %s, pc mic recoder is busy!\n", __func__);
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"pc_mic");
|
||||
if (uuid == 0) {
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
return -EFAULT;
|
||||
}
|
||||
recoder = zalloc(sizeof(*recoder));
|
||||
if (!recoder) {
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
|
||||
source_uuid = NODE_UUID_ADC;
|
||||
|
||||
if (!recoder->stream) {
|
||||
goto __exit0;
|
||||
}
|
||||
|
||||
//设置ADC的中断点数
|
||||
int err = jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, AUDIO_ADC_IRQ_POINTS);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
u16 node_uuid = get_cvp_node_uuid();
|
||||
//根据回音消除的类型,将配置传递到对应的节点
|
||||
if (node_uuid) {
|
||||
#if !(TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE))
|
||||
u32 ref_sr = audio_dac_get_sample_rate(&dac_hdl);
|
||||
jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
|
||||
#endif
|
||||
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_PRIV_FMT, source_uuid);
|
||||
if (err && (err != -ENOENT)) { //兼容没有cvp节点的情况
|
||||
goto __exit1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jlstream_set_callback(recoder->stream, recoder->stream, pc_mic_recoder_callback);
|
||||
jlstream_set_scene(recoder->stream, STREAM_SCENE_PC_MIC);
|
||||
err = jlstream_start(recoder->stream);
|
||||
if (err) {
|
||||
goto __exit1;
|
||||
}
|
||||
|
||||
g_pc_mic_state = PC_MIC_STA_OPEN;
|
||||
g_pc_mic_recoder = recoder;
|
||||
|
||||
pcm_mic_recoder_dump(pcm_mic_recoder_check);
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
return 0;
|
||||
|
||||
__exit1:
|
||||
jlstream_release(recoder->stream);
|
||||
__exit0:
|
||||
free(recoder);
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
void pc_mic_recoder_close(void)
|
||||
{
|
||||
os_mutex_pend(&mic_rec_mutex, 0);
|
||||
struct pc_mic_recoder *recoder = g_pc_mic_recoder;
|
||||
|
||||
if (!recoder) {
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
return;
|
||||
}
|
||||
if (recoder->stream) {
|
||||
jlstream_stop(recoder->stream, 0);
|
||||
jlstream_release(recoder->stream);
|
||||
}
|
||||
|
||||
free(recoder);
|
||||
g_pc_mic_recoder = NULL;
|
||||
pcm_mic_recoder_check = 0;
|
||||
|
||||
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"pc_mic");
|
||||
os_mutex_post(&mic_rec_mutex);
|
||||
g_pc_mic_state = PC_MIC_STA_CLOSE;
|
||||
}
|
||||
|
||||
//重启pc mic
|
||||
static void pc_mic_recoder_restart(void)
|
||||
{
|
||||
if (g_pc_mic_state == PC_MIC_STA_OPEN) {
|
||||
pc_mic_recoder_close();
|
||||
pc_mic_recoder_open();
|
||||
}
|
||||
}
|
||||
|
||||
bool pc_mic_recoder_runing()
|
||||
{
|
||||
return g_pc_mic_recoder != NULL;
|
||||
}
|
||||
|
||||
int pc_mic_recoder_open_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = 0;
|
||||
if (g_pc_mic_state == PC_MIC_STA_CLOSE ||
|
||||
g_pc_mic_state == PC_MIC_STA_WAIT_CLOSE) {
|
||||
|
||||
g_pc_mic_state = PC_MIC_STA_WAIT_OPEN;
|
||||
msg[0] = (int)pc_mic_recoder_open;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pc_mic_recoder_close_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = 0;
|
||||
if (g_pc_mic_state == PC_MIC_STA_OPEN ||
|
||||
g_pc_mic_state == PC_MIC_STA_WAIT_OPEN) {
|
||||
|
||||
g_pc_mic_state = PC_MIC_STA_WAIT_CLOSE;
|
||||
msg[0] = (int)pc_mic_recoder_close;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pc_mic_recoder_restart_by_taskq(void)
|
||||
{
|
||||
int msg[2];
|
||||
int ret = 0;
|
||||
msg[0] = (int)pc_mic_recoder_restart;
|
||||
msg[1] = 0;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pc_mic_set_volume(int mic_vol)
|
||||
{
|
||||
pcmic_volume_wait_set_flag = 0;
|
||||
if (app_get_current_mode()->name == APP_MODE_PC) {
|
||||
s16 volume = (u16)mic_vol;
|
||||
|
||||
struct volume_cfg cfg = {0};
|
||||
cfg.bypass = VOLUME_NODE_CMD_SET_VOL;
|
||||
cfg.cur_vol = volume;
|
||||
|
||||
int err = jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, "Vol_PcMic", (void *)&cfg, sizeof(struct volume_cfg));
|
||||
log_debug(">>> pc mic vol: %d, ret:%d", mic_vol, err);
|
||||
}
|
||||
}
|
||||
|
||||
int pc_mic_set_volume_by_taskq(u32 mic_vol)
|
||||
{
|
||||
int ret = 0;
|
||||
if (pcmic_volume_wait_set_flag == 0) {
|
||||
int msg[3];
|
||||
msg[0] = (int)pc_mic_set_volume;
|
||||
msg[1] = 1;
|
||||
msg[2] = (int)mic_vol;
|
||||
ret = os_taskq_post_type("app_core", Q_CALLBACK, sizeof(msg) / sizeof(int), msg);
|
||||
if (ret == 0) {
|
||||
pcmic_volume_wait_set_flag = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user