first
This commit is contained in:
255
apps/earphone/bt_background.c
Normal file
255
apps/earphone/bt_background.c
Normal file
@ -0,0 +1,255 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user