Files
99_7018_lmx/apps/earphone/bt_background.c
2025-10-29 13:10:02 +08:00

256 lines
6.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}