Files
99_7018_lmx/apps/earphone/bt_background.c

256 lines
6.7 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
#include "system/includes.h"
#include "classic/tws_api.h"
#include "btstack/avctp_user.h"
#include "btstack/a2dp_media_codec.h"
#include "app_config.h"
#include "app_main.h"
#include "app_action.h"
#include "app_task.h"
#include "audio_config.h"
static u16 clear_to_seqn = 0;
static u16 slience_timer;
static u8 unmute_packet_cnt;
static u8 g_bt_background = 0;
static u8 energy_check_stop;
u8 bt_media_is_running();
void a2dp_dec_close();
void bt_switch_to_foreground(int action, bool exit_curr_app);
#define TWS_A2DP_CLEAR_ID TWS_FUNC_ID('A', 2, 'C', 'R')
static void __tws_a2dp_clear_to_seqn(void *data, u16 len, bool rx)
{
if (rx) {
clear_to_seqn = *(u16 *)data;
}
}
REGISTER_TWS_FUNC_STUB(tws_a2dp_clear_to_seqn) = {
.func_id = TWS_A2DP_CLEAR_ID,
.func = __tws_a2dp_clear_to_seqn,
};
bool bt_in_background()
{
return g_bt_background;
}
void a2dp_slience_detect(void *p)
{
int len;
u8 *packet;
int ingore_packet_num = (int)p;
int role = tws_api_get_role();
u32 media_type;
putchar('^');
while (1) {
media_type = a2dp_media_get_codec_type();
len = a2dp_media_try_get_packet(&packet);
if (len <= 0) {
break;
}
u16 seqn = (packet[2] << 8) | packet[3];
if (role == TWS_ROLE_MASTER) {
if (clear_to_seqn == 0) {
clear_to_seqn = seqn + ingore_packet_num;
if (clear_to_seqn == 0) {
clear_to_seqn = 1;
}
a2dp_media_free_packet(packet);
a2dp_media_clear_packet_before_seqn(clear_to_seqn);
break;
}
//能量检测
if (energy_check_stop == 0) {
int energy;
if (media_type == 0) {
energy = sbc_energy_check(packet, len);
} else {
energy = aac_energy_check(packet, len);
}
printf("energy:media_type= %d,%d, %d, %d\n", media_type, seqn, energy, unmute_packet_cnt);
if (energy >= 10) {
if (++unmute_packet_cnt >= 20) {
unmute_packet_cnt = 0;
energy_check_stop = 1;
//能量检测结束,通知从机丢到指定包号数据然后开始A2DP解码
clear_to_seqn = seqn + 10;
if (clear_to_seqn == 0) {
clear_to_seqn = 1;
}
tws_api_send_data_to_slave(&clear_to_seqn, 2, TWS_A2DP_CLEAR_ID);
}
} else {
unmute_packet_cnt >>= 1;
}
a2dp_media_free_packet(packet);
continue;
}
}
printf("seqn: %d, %d\n", seqn, clear_to_seqn);
a2dp_media_free_packet(packet);
if (clear_to_seqn && seqn_after(seqn, clear_to_seqn)) {
clear_to_seqn = 0;
sys_timer_del(slience_timer);
slience_timer = 0;
if (!bt_in_background()) {
//先点击手机播放再立马按键切模式时此处需要打开a2dp解码
g_bt_background = 1;
bt_switch_to_foreground(ACTION_A2DP_START, 0);
} else {
app_task_switch_to(APP_BT_TASK, ACTION_A2DP_START);
}
break;
}
}
}
void bt_start_a2dp_slience_detect(int ingore_packet_num)
{
if (slience_timer) {
sys_timer_del(slience_timer);
}
clear_to_seqn = 0;
unmute_packet_cnt = 0;
energy_check_stop = 0;
slience_timer = sys_timer_add((void *)ingore_packet_num, a2dp_slience_detect, 40);
g_printf("bt_start_a2dp_slience_detect=%d\n", slience_timer);
}
void bt_stop_a2dp_slience_detect()
{
if (slience_timer) {
sys_timer_del(slience_timer);
g_printf("bt_stop_a2dp_slience_detect");
slience_timer = 0;
}
}
int bt_switch_to_background()
{
int a2dp_state;
int esco_state;
struct intent it;
if (app_var.siri_stu && app_var.siri_stu != 3 && get_esco_busy_flag()) {
// siri不退出
return -EINVAL;
}
esco_state = get_call_status();
if (esco_state == BT_CALL_OUTGOING ||
esco_state == BT_CALL_ALERT ||
esco_state == BT_CALL_INCOMING ||
esco_state == BT_CALL_ACTIVE) {
// 通话不退出
return -EINVAL;
}
a2dp_state = a2dp_get_status();
r_printf("a2dp_state=%d\n", a2dp_state);
if ((tws_api_get_role() == TWS_ROLE_MASTER) && (a2dp_state == BT_MUSIC_STATUS_STARTING)) {
user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PAUSE, 0, NULL);
}
if (bt_media_is_running()) {
a2dp_dec_close();
a2dp_media_clear_packet_before_seqn(0);
bt_start_a2dp_slience_detect(30);
}
g_bt_background = 1;
return 0;
}
void bt_switch_to_foreground(int action, bool exit_curr_app)
{
struct intent it;
if (g_bt_background) {
g_bt_background = 0;
/* 退出当前模式 */
if (exit_curr_app) {
init_intent(&it);
it.action = ACTION_BACK;
start_app(&it);
}
}
if (action) {
init_intent(&it);
it.name = "earphone";
it.action = action;
start_app(&it);
}
}
int bt_background_event_probe_handler(struct bt_event *bt)
{
int len;
switch (bt->event) {
case BT_STATUS_INIT_OK:
len = syscfg_read(CFG_HAVE_MASS_STORAGE, &app_var.have_mass_storage, 1);
if (len != 1) {
if (dev_online("sd0")) {
app_var.have_mass_storage = 1;
syscfg_write(CFG_HAVE_MASS_STORAGE, &app_var.have_mass_storage, 1);
}
}
printf("have_mass_storage: %d\n", app_var.have_mass_storage);
break;
case BT_STATUS_A2DP_MEDIA_START:
puts("BT_STATUS_A2DP_MEDIA_START\n");
if (bt_in_background()) {
bt_start_a2dp_slience_detect(30);
return -EINVAL;
} else {
bt_stop_a2dp_slience_detect();
}
break;
case BT_STATUS_A2DP_MEDIA_STOP:
puts("BT_STATUS_A2DP_MEDIA_STOP\n");
if (bt_in_background()) {
bt_stop_a2dp_slience_detect();
extern void free_a2dp_using_decoder_conn();
free_a2dp_using_decoder_conn();
return -EINVAL;
}
break;
case BT_STATUS_VOICE_RECOGNITION:
if (bt->value && bt->value != 3) {
} else {
break;
}
case BT_STATUS_PHONE_INCOME:
case BT_STATUS_PHONE_OUT:
case BT_STATUS_PHONE_ACTIVE:
bt_switch_to_foreground(ACTION_DO_NOTHING, 0);
break;
}
return 0;
}