877 lines
36 KiB
C
877 lines
36 KiB
C
#include "ble_port_a2dp_service.h"
|
||
#include "audio_manager_c_wrapper.h"
|
||
#include "ble_api.h"
|
||
#include "bt_audio.h"
|
||
#include "bt_audio_hal_interface.h"
|
||
#include "bts_a2dp_sink.h"
|
||
#include "bts_a2dp_source.h"
|
||
#include "bts_avrcp_controller.h"
|
||
#include "bts_avrcp_target.h"
|
||
#include "osal_addr.h"
|
||
#include "osal_timer.h"
|
||
#include "soc_errno.h"
|
||
#include "sys_config.h"
|
||
|
||
#define ENABLE_PRINT_INFO 1
|
||
#if ENABLE_PRINT_INFO
|
||
#define static_print_debug(...) sys_bt_log_d(__VA_ARGS__) // 一般信息打印宏控制
|
||
#define static_print_warn(...) sys_bt_log_w(__VA_ARGS__) // 警告信息打印一般常开
|
||
#define static_print_error(...) sys_bt_log_e(__VA_ARGS__) // 错误信息打印一般常开
|
||
#else
|
||
#define static_print_debug(...)
|
||
#define static_print_warn(...)
|
||
#define static_print_error(...)
|
||
#endif
|
||
|
||
#define AVRCP_CT_AUTO_REG_TYPE 1
|
||
#define AVRCP_CT_AUTO_REG_NON 0
|
||
#define BTS_ATTR_ID_LEN 4
|
||
#define BTS_ATTR_LIST_LEN 12
|
||
#define BTS_UID_LEN 8
|
||
#define MAX_SAMPLE_AVRCP_CT_REG_CNT 5 // 支持一次shell命令最多能注册5个事件
|
||
#define AVRCP_SHIFT_BITS_32 32
|
||
#define LONG_MIN (-LONG_MAX - 1)
|
||
#define LONG_MAX 2147483647L
|
||
#define A2DP_STREAM_ACCEPT_TIMER_PERIOD 500
|
||
|
||
#define BLUETOOTH_MAX_NUM 20
|
||
#define MEDIA_A2DP_SNK_INTERFACE 1
|
||
#define MEMORY_MINI 1
|
||
|
||
enum
|
||
{
|
||
AVRCP_SRV_PRESS_VALUE,
|
||
AVRCP_SRV_RELEASED_VALUE,
|
||
AVRCP_SRV_INIT_VALUE
|
||
};
|
||
|
||
enum
|
||
{
|
||
SAMPLE_A2DP_STREAM_UNKNOWN, /* no a2dp */
|
||
SAMPLE_A2DP_STREAM_CREATE,
|
||
SAMPLE_A2DP_STREAM_OPENED,
|
||
SAMPLE_A2DP_STREAM_START,
|
||
SAMPLE_A2DP_STREAM_SUSPENDED,
|
||
SAMPLE_A2DP_STREAM_CLOSED
|
||
};
|
||
|
||
// typedef void *td_pvoid;
|
||
|
||
typedef struct
|
||
{
|
||
td_pvoid stream_hdl;
|
||
uint8_t loc_volume;
|
||
uint8_t play_stat;
|
||
uint8_t dir_forward;
|
||
uint8_t avrcp_button_flag;
|
||
bd_addr_t bd_addr;
|
||
uint8_t reg_cap_auto;
|
||
uint8_t resrv;
|
||
profile_connect_state_t avrcp_srv_conn_stat;
|
||
} sample_avrcp_tg_sample_inf;
|
||
sample_avrcp_tg_sample_inf g_tjd_avrcp_srv_inf;
|
||
|
||
static src_connect_state_callback_t g_src_connect_state_callback = NULL;
|
||
static snk_connect_state_callback_t g_snk_connect_state_callback = NULL;
|
||
static playing_state_callback_t g_playing_state_callback = NULL;
|
||
// static uint32_t g_tjd_hid_service_handle = 0;
|
||
static sync_lrc_callback_t g_sync_lrc_callback = NULL;
|
||
|
||
osal_timer g_tjd_a2dp_stream_accept_timer = {0};
|
||
static bool isFirst = false;
|
||
|
||
extern AudioFormatConfig g_audio_format_config;
|
||
|
||
#pragma region a2dp src
|
||
/****************************
|
||
* A2DP SRC
|
||
*/
|
||
// static void A2dpSrcConnectstateChanged(bd_addr_t *bdAddr, int connState)
|
||
// {
|
||
// static_print_debug("a2dp_src_connectStateChangedCallback addr: %02x%02x%02x%02x%02x%02x connState: %x",
|
||
// bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* 5 4 3 idx */
|
||
// bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], connState); /* 2 1 0 idx */
|
||
// if ((gap_get_device_class(bdAddr) & 0x200) != 0) {
|
||
// static_print_debug("a2dp_src_connectstateChangedCb: Mobile Phone Device");
|
||
// return;
|
||
// }
|
||
// if (connState == PROFILE_STATE_CONNECTED) {
|
||
// avrcp_ct_connect(bdAddr);
|
||
// }
|
||
// else if (connState == PROFILE_STATE_DISCONNECTED) {
|
||
// static_print_debug("a2dp_src_connectstateChangedCb: Disconnected");
|
||
// }
|
||
// }
|
||
|
||
// static void A2dpSrcConfigureChanged(bd_addr_t *bdAddr, a2dp_codec_info_t *info)
|
||
// {
|
||
// static_print_debug("A2dpSrcConfigurationChangedCallback addr: %02x%02x%02x%02x%02x%02x ",
|
||
// bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* 5 4 3 idx */
|
||
// bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0]); /* 2 1 0 idx */
|
||
// static_print_debug("codec_priority: %04x codec_type: %04x sample_rate: %02x bits_per_sample: %02x channel_mode:
|
||
// %02x ",
|
||
// info->codec_priority, info->codec_type, info->sample_rate, info->bits_per_sample, info->channel_mode);
|
||
// static_print_debug("codec_specific1: %04x codec_specific2: %04x codec_specific3: %04x codec_specific4: %04x",
|
||
// info->codec_specific1, info->codec_specific2, info->codec_specific3, info->codec_specific4);
|
||
// }
|
||
|
||
// static void A2dpSrcPlayingStateChanged(bd_addr_t *bdAddr, int playState)
|
||
// {
|
||
// static_print_debug("A2dpSrcPlayingStateChangedCallback addr: %02x%02x%02x%02x%02x%02x playState: %x",
|
||
// bdAddr->addr[5], bdAddr->addr[4], bdAddr->addr[3], /* 5 4 3 idx */
|
||
// bdAddr->addr[2], bdAddr->addr[1], bdAddr->addr[0], playState); /* 2 1 0 idx */
|
||
// }
|
||
|
||
static void sample_a2dp_src_connect_state_changed_callback(const bd_addr_t *bd_addr, int conn_state)
|
||
{
|
||
static_print_debug("addr: ****%02x%02x%02x%02x conn_state: %x", bd_addr->addr[3], bd_addr->addr[2],
|
||
bd_addr->addr[1], bd_addr->addr[0], conn_state); /* 3 2 1 0 idx */
|
||
|
||
if (g_src_connect_state_callback != NULL) {
|
||
static_print_debug("g_src_connect_state_callback");
|
||
g_src_connect_state_callback(conn_state);
|
||
}
|
||
if (conn_state == PROFILE_STATE_CONNECTED) {
|
||
avrcp_ct_connect(bd_addr);
|
||
audio_manager_set_device_connection_state(OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_CONNECTED);
|
||
} else if (conn_state == PROFILE_STATE_DISCONNECTING) {
|
||
|
||
} else if (conn_state == PROFILE_STATE_DISCONNECTED) {
|
||
audio_manager_set_device_connection_state(OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_DISCONNECTED);
|
||
}
|
||
// static_print_debug("addr: ****%02x%02x%02x%02x conn_state: %x",
|
||
// bd_addr->addr[3], bd_addr->addr[2], bd_addr->addr[1], bd_addr->addr[0], conn_state); /* 3 2 1 0 idx */
|
||
|
||
// if (conn_state == PROFILE_STATE_CONNECTED) {
|
||
// /* A2DP 连接建立成功后,主动建立AVRCP连接 */
|
||
// int conn_ret = avrcp_ct_connect(bd_addr);
|
||
// if (conn_ret != ERRCODE_BT_SUCCESS) {
|
||
// static_print_debug("avrcp_ct_connect failed, ret: %d", conn_ret);
|
||
// }
|
||
// }
|
||
// else if (conn_state == PROFILE_STATE_DISCONNECTED) {
|
||
// /* A2DP 连接断开后,主动断开AVRCP连接 */
|
||
// int disconn_ret = avrcp_ct_disconnect(bd_addr);
|
||
// if (disconn_ret != ERRCODE_BT_SUCCESS) {
|
||
// static_print_debug("avrcp_ct_disconnect failed, ret: %d", disconn_ret);
|
||
// }
|
||
// }
|
||
}
|
||
|
||
static void sample_a2dp_src_configuration_changed_callback(const bd_addr_t *bd_addr, const a2dp_codec_info_t *info)
|
||
{
|
||
static_print_debug("addr: ****%02x%02x%02x%02x ", bd_addr->addr[3], bd_addr->addr[2], bd_addr->addr[1],
|
||
bd_addr->addr[0]); /* 3 2 1 0 idx */
|
||
static_print_debug(
|
||
"codec_priority: %04x codec_type: %04x sample_rate: %02x bits_per_sample: %02x channel_mode: %02x",
|
||
info->codec_priority, info->codec_type, info->sample_rate, info->bits_per_sample, info->channel_mode);
|
||
static_print_debug("codec_specific1: %04x codec_specific2: %04x codec_specific3: %04x codec_specific4: %04x",
|
||
(unsigned int)info->codec_specific1, (unsigned int)info->codec_specific2,
|
||
(unsigned int)info->codec_specific3, (unsigned int)info->codec_specific4);
|
||
}
|
||
|
||
static void sample_a2dp_src_playing_state_changed_callback(const bd_addr_t *bd_addr, int playing_state)
|
||
{
|
||
static_print_debug("addr: ****%02x%02x%02x%02x playing_state: %x", bd_addr->addr[3], bd_addr->addr[2],
|
||
bd_addr->addr[1], bd_addr->addr[0], playing_state); /* 3 2 1 0 idx */
|
||
/* 播放状态变化通知CT */
|
||
avrcp_tg_notify_playback_status_changed((unsigned char)playing_state);
|
||
}
|
||
|
||
void register_a2dpsrc_servers_callbacks(void)
|
||
{
|
||
static a2dp_src_callbacks_t g_sample_a2dp_src_callbacks = {
|
||
.connectstate_changed_cb = sample_a2dp_src_connect_state_changed_callback,
|
||
.configuration_changed_cb = sample_a2dp_src_configuration_changed_callback,
|
||
.playing_state_changed_cb = sample_a2dp_src_playing_state_changed_callback};
|
||
|
||
int ret = a2dp_src_register_callbacks(&g_sample_a2dp_src_callbacks);
|
||
if (ret != ERRCODE_BT_SUCCESS) {
|
||
static_print_debug("a2dp_src_register_callbacks failed, ret: %d", ret);
|
||
}
|
||
audio_manager_init(AUDIO_STREAM_MUSIC);
|
||
}
|
||
#pragma endregion
|
||
|
||
#pragma region a2dp snk
|
||
/************************************************************************
|
||
* A2DP SINK Server
|
||
*/
|
||
|
||
static void sample_a2dp_snk_connect_state_changed_callback(const bd_addr_t *bd_addr, int conn_state)
|
||
{
|
||
// static_print_debug("sample_a2dp_snk_connect_state_changed_callback ba_addr: %p ",bd_addr);
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("sample_a2dp_snk_connect_state_changed_callback: bd_addr is NULL");
|
||
return;
|
||
}
|
||
static_print_debug("a2dp_snk_connect_state_changed_callback addr: ****%02x%02x%02x%02x conn_state: %x",
|
||
bd_addr->addr[3], bd_addr->addr[2], bd_addr->addr[1], bd_addr->addr[0],
|
||
conn_state); /* 3 2 1 0 idx */
|
||
|
||
if (g_snk_connect_state_callback != NULL) {
|
||
static_print_debug("g_snk_connect_state_callback");
|
||
g_snk_connect_state_callback(conn_state);
|
||
}
|
||
|
||
if (conn_state == PROFILE_STATE_CONNECTED) {
|
||
/* A2DP 连接建立成功后,主动建立AVRCP连接 */
|
||
int conn_ret = avrcp_tg_connect(bd_addr);
|
||
if (conn_ret != ERRCODE_BT_SUCCESS) {
|
||
static_print_debug("avrcp_tg_connect failed, ret: %x", conn_ret);
|
||
}
|
||
static_print_debug("test mode auto reg");
|
||
g_tjd_avrcp_srv_inf.avrcp_button_flag = AVRCP_SRV_RELEASED_VALUE;
|
||
g_tjd_avrcp_srv_inf.reg_cap_auto = AVRCP_CT_AUTO_REG_TYPE;
|
||
conn_ret = avrcp_ct_connect(bd_addr);
|
||
if (conn_ret != ERRCODE_BT_SUCCESS) {
|
||
static_print_debug("avrcp_ct_connect failed, ret: %x", conn_ret);
|
||
}
|
||
}
|
||
|
||
if (conn_state == PROFILE_STATE_DISCONNECTED) {
|
||
/* A2DP 连接断开后,主动断开AVRCP连接 */
|
||
int disconn_ret = avrcp_tg_disconnect(bd_addr);
|
||
if (disconn_ret != ERRCODE_BT_SUCCESS) {
|
||
static_print_debug("avrcp_tg_disconnect failed, ret: %x", disconn_ret);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void sample_a2dp_snk_accept_timer_stop(void)
|
||
{
|
||
static_print_debug("stop timer");
|
||
if (g_tjd_a2dp_stream_accept_timer.timer != NULL) {
|
||
(void)osal_timer_stop(&g_tjd_a2dp_stream_accept_timer);
|
||
(void)osal_timer_destroy(&g_tjd_a2dp_stream_accept_timer);
|
||
g_tjd_a2dp_stream_accept_timer.timer = NULL;
|
||
}
|
||
static_print_debug("stop timer success!");
|
||
}
|
||
|
||
bool g_isA2dpSnkConnected = false;
|
||
static void sample_a2dp_snk_start_accept_handler(unsigned long data)
|
||
{
|
||
static_print_debug("sample_a2dp_snk_start_accept_handler");
|
||
// bts_unused(data);
|
||
// if (g_isA2dpSnkConnected) {
|
||
bd_addr_t active_bd_addr = a2dp_snk_get_active_device();
|
||
a2dp_snk_start_accept(&active_bd_addr);
|
||
sample_a2dp_snk_accept_timer_stop();
|
||
// }
|
||
}
|
||
|
||
static int32_t sample_a2dp_snk_start_accept_timer(void)
|
||
{
|
||
static_print_debug("start timer");
|
||
if (g_tjd_a2dp_stream_accept_timer.timer != NULL) {
|
||
static_print_debug("timer is running");
|
||
return EXT_ERR_SUCCESS;
|
||
}
|
||
|
||
g_tjd_a2dp_stream_accept_timer.handler = sample_a2dp_snk_start_accept_handler;
|
||
g_tjd_a2dp_stream_accept_timer.interval = A2DP_STREAM_ACCEPT_TIMER_PERIOD;
|
||
|
||
int32_t timer_ret = osal_timer_init(&g_tjd_a2dp_stream_accept_timer);
|
||
if (timer_ret != EOK) {
|
||
static_print_debug("create timer error! ret: %x", timer_ret);
|
||
sample_a2dp_snk_accept_timer_stop();
|
||
return EXT_ERR_FAILURE;
|
||
}
|
||
timer_ret = osal_timer_start(&g_tjd_a2dp_stream_accept_timer);
|
||
if (timer_ret != EOK) {
|
||
static_print_debug("start timer error! ret: %x", timer_ret);
|
||
sample_a2dp_snk_accept_timer_stop();
|
||
return EXT_ERR_FAILURE;
|
||
}
|
||
return EXT_ERR_SUCCESS;
|
||
}
|
||
|
||
static int32_t sample_a2dp_snk_audio_create(void)
|
||
{
|
||
#if MEDIA_A2DP_SNK_INTERFACE
|
||
static_print_debug("audioFormat %d channelCount %d sampleRate %u ", g_audio_format_config.audioFormat,
|
||
g_audio_format_config.channelCount, g_audio_format_config.sampleRate);
|
||
// g_audio_format_config.audioFormat =
|
||
int32_t ret = AudioManagerA2dpSinkSetParam(g_audio_format_config);
|
||
static_print_debug("AudioManagerA2dpSinkSetParam ret %x", ret);
|
||
ret = AudioManagerA2dpSinkCreate();
|
||
static_print_debug("AudioManagerA2dpSinkCreate ret %x", ret);
|
||
#endif
|
||
/* 起定时器接受音乐开始请求 */
|
||
sample_a2dp_snk_start_accept_timer();
|
||
return 0;
|
||
}
|
||
|
||
static void sample_a2dp_snk_start_stream_request_callback(const bd_addr_t *bd_addr)
|
||
{
|
||
// static_print_debug("sample_a2dp_snk_start_stream_request_callback ba_addr: %p ",bd_addr);
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("sample_a2dp_snk_start_stream_request_callback: bd_addr is NULL");
|
||
return;
|
||
}
|
||
static_print_debug("a2dp_snk_start_stream_request_callback addr: ****%02x%02x%02x%02x ", bd_addr->addr[3],
|
||
bd_addr->addr[2], bd_addr->addr[1], bd_addr->addr[0]); /* 3 2 1 0 idx */
|
||
sample_a2dp_snk_audio_create();
|
||
}
|
||
|
||
static int32_t sample_a2dp_snk_audio_destroy(void)
|
||
{
|
||
#if MEDIA_A2DP_SNK_INTERFACE
|
||
int32_t ret = AudioManagerA2dpSinkDestroy();
|
||
static_print_debug("AudioManagerA2dpSinkDestroy ret %x", ret);
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
static void sample_a2dp_snk_playing_state_changed_callback(const bd_addr_t *bd_addr, int playing_state)
|
||
{
|
||
// static_print_debug("sample_a2dp_snk_playing_state_changed_callback ba_addr: %p ",bd_addr);
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("sample_a2dp_snk_playing_state_changed_callback: bd_addr is NULL");
|
||
return;
|
||
}
|
||
static_print_debug("a2dp_snk_playing_state_changed_callback addr: ****%02x%02x%02x%02x playing_state: %x",
|
||
bd_addr->addr[3], bd_addr->addr[2], bd_addr->addr[1], bd_addr->addr[0],
|
||
playing_state); /* 3 2 1 0 idx */
|
||
|
||
if (playing_state == A2DP_NOT_PLAYING) {
|
||
sample_a2dp_snk_audio_destroy();
|
||
}
|
||
|
||
// }else if (playing_state == A2DP_IS_PLAYING){
|
||
// static_print_debug("a2dp is playing...");
|
||
// // avrcp_ct_get_element_attr_para_t element_attr_param;
|
||
// // element_attr_param.attr_num = AVRCP_CT_ELEMENT_ATTR_TRACK_PLAYING_TIME;
|
||
// // element_attr_param.attr_id_list =
|
||
// // (unsigned int *)(void *)osal_kmalloc(sizeof(unsigned int) *
|
||
// element_attr_param.attr_num,OSAL_GFP_KERNEL);
|
||
// // for (int i = 0; i < element_attr_param.attr_num; i++) {
|
||
// // element_attr_param.attr_id_list[i] = (unsigned int)i + 1;
|
||
// // }
|
||
// // avrcp_ct_get_element_attributes(bd_addr,&element_attr_param);
|
||
// // if (element_attr_param.attr_id_list != NULL) {
|
||
// // osal_kfree(element_attr_param.attr_id_list);
|
||
// // element_attr_param.attr_id_list = NULL;
|
||
// // }
|
||
// }
|
||
}
|
||
|
||
static void sample_a2dp_snk_configuration_changed_callback(const bd_addr_t *bd_addr, const a2dp_snk_codec_info_t *info)
|
||
{
|
||
// static_print_debug("sample_a2dp_snk_configuration_changed_callback ba_addr: %p info: %p",bd_addr,info);
|
||
if (bd_addr == NULL || info == NULL) {
|
||
static_print_debug("sample_a2dp_snk_configuration_changed_callback: bd_addr or infois NULL");
|
||
return;
|
||
}
|
||
static_print_debug("a2dp_snk_configuration_changed_callback addr: ****%02x%02x%02x%02x ", bd_addr->addr[3],
|
||
bd_addr->addr[2], bd_addr->addr[1], bd_addr->addr[0]); /* 3 2 1 0 idx */
|
||
static_print_debug(
|
||
"codec_priority: %04x codec_type: %04x sample_rate: %02x bits_per_sample: %02x channel_mode: %02x",
|
||
info->codec_priority, info->codec_type, info->sample_rate, info->bits_per_sample, info->channel_mode);
|
||
static_print_debug("codec_specific1: %04x codec_specific2: %04x codec_specific3: %04x codec_specific4: %04x",
|
||
(unsigned int)info->codec_specific1, (unsigned int)info->codec_specific2,
|
||
(unsigned int)info->codec_specific3, (unsigned int)info->codec_specific4);
|
||
#if MEDIA_A2DP_SNK_INTERFACE
|
||
if (info->codec_type == A2DP_SNK_CODEC_TYPE_AAC) {
|
||
g_audio_format_config.audioFormat = AAC_LC;
|
||
} else {
|
||
g_audio_format_config.audioFormat = SBC;
|
||
}
|
||
/* channel count 1 or 2 */
|
||
g_audio_format_config.channelCount = (info->channel_mode == A2DP_SNK_CODEC_CHANNEL_MODE_NONE ? 1 : 2);
|
||
|
||
switch (info->sample_rate) {
|
||
case A2DP_SNK_CODEC_SAMPLE_RATE_48000:
|
||
g_audio_format_config.sampleRate = BT_AUDIO_A2DP_SMAPLE_RATE48000;
|
||
break;
|
||
case A2DP_SNK_CODEC_SAMPLE_RATE_88200:
|
||
g_audio_format_config.sampleRate = BT_AUDIO_A2DP_SMAPLE_RATE88200;
|
||
break;
|
||
case A2DP_SNK_CODEC_SAMPLE_RATE_96000:
|
||
g_audio_format_config.sampleRate = BT_AUDIO_A2DP_SMAPLE_RATE96000;
|
||
break;
|
||
default:
|
||
g_audio_format_config.sampleRate = BT_AUDIO_A2DP_SMAPLE_RATE44100;
|
||
break;
|
||
}
|
||
static_print_debug("audioFormat %d channelCount %d sampleRate %u ", g_audio_format_config.audioFormat,
|
||
g_audio_format_config.channelCount, g_audio_format_config.sampleRate);
|
||
#endif
|
||
}
|
||
|
||
void register_a2dpsnk_servers_callback(void)
|
||
{
|
||
static a2dp_snk_callbacks_t g_sample_a2dp_snk_callbacks = {
|
||
.connectstate_changed_cb = sample_a2dp_snk_connect_state_changed_callback,
|
||
.start_stream_request_cb = sample_a2dp_snk_start_stream_request_callback,
|
||
.playing_state_changed_cb = sample_a2dp_snk_playing_state_changed_callback,
|
||
.configuration_changed_cb = sample_a2dp_snk_configuration_changed_callback};
|
||
|
||
int ret = a2dp_snk_register_callbacks(&g_sample_a2dp_snk_callbacks);
|
||
if (ret != ERRCODE_BT_SUCCESS) {
|
||
static_print_debug("a2dp_snk_register_callbacks ret(int): %x", ret);
|
||
}
|
||
}
|
||
#pragma endregion
|
||
|
||
#pragma region avrcp ct server
|
||
/*************************************************************
|
||
* AVRCP CT SERVER
|
||
*/
|
||
static bd_addr_t *sample_avrcp_srv_get_active_addr(void) { return &g_tjd_avrcp_srv_inf.bd_addr; }
|
||
|
||
static void sample_avrcp_ct_connect_state_changed_callback(const bd_addr_t *bd_addr, profile_connect_state_t state)
|
||
{
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("avrcp ct update conn stat:%u", state);
|
||
(void)memcpy_s(g_tjd_avrcp_srv_inf.bd_addr.addr, BD_ADDR_LEN, bd_addr->addr, BD_ADDR_LEN);
|
||
static_print_debug("addr: ****%02x%02x%02x%02x ", bd_addr->addr[3], bd_addr->addr[2], bd_addr->addr[1],
|
||
bd_addr->addr[0]); /* 3 2 1 0 idx */
|
||
g_tjd_avrcp_srv_inf.avrcp_srv_conn_stat = state;
|
||
avrcp_ct_get_supported_events(g_tjd_avrcp_srv_inf.bd_addr.addr);
|
||
}
|
||
|
||
static void sample_avrcp_ct_press_button_rsp_cbk(const bd_addr_t *bd_addr, int32_t key_operation)
|
||
{
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("avrcp ct press button rsp_cbk key:%d", key_operation);
|
||
if (g_tjd_avrcp_srv_inf.avrcp_button_flag == AVRCP_SRV_RELEASED_VALUE) {
|
||
static_print_debug("avrcp ct press button button_flag change:%u->%u", g_tjd_avrcp_srv_inf.avrcp_button_flag,
|
||
AVRCP_SRV_PRESS_VALUE);
|
||
g_tjd_avrcp_srv_inf.avrcp_button_flag = AVRCP_SRV_PRESS_VALUE;
|
||
}
|
||
static_print_debug("avrcp ct press button cbk key:%d button_flag:%u", key_operation,
|
||
g_tjd_avrcp_srv_inf.avrcp_button_flag);
|
||
}
|
||
|
||
static void sample_avrcp_press_release_button_log(uint32_t key_operation)
|
||
{
|
||
switch (key_operation) {
|
||
case AVRCP_KEY_VOLUME_UP:
|
||
static_print_debug("AVRCP_KEY_VOLUME_UP");
|
||
break;
|
||
case AVRCP_KEY_VOLUME_DOWN:
|
||
static_print_debug("AVRCP_KEY_VOLUME_DOWN");
|
||
break;
|
||
case AVRCP_KEY_MUTE:
|
||
static_print_debug("AVRCP_KEY_VOLUME_MUTE");
|
||
break;
|
||
case AVRCP_KEY_PLAY:
|
||
static_print_debug("AVRCP_KEY_PLAY");
|
||
break;
|
||
case AVRCP_KEY_STOP:
|
||
static_print_debug("AVRCP_KEY_STOP");
|
||
break;
|
||
case AVRCP_KEY_PAUSE:
|
||
static_print_debug("AVRCP_KEY_PAUSE");
|
||
break;
|
||
case AVRCP_KEY_FORWARD:
|
||
static_print_debug("AVRCP_KEY_FORWARD");
|
||
break;
|
||
case AVRCP_KEY_BACKWARD:
|
||
static_print_debug("AVRCP_KEY_BACKWARD");
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_VOLUME_CHANGED:
|
||
static_print_debug("AVRCP_EVENT_VOLUME_CHANGED");
|
||
break;
|
||
default:
|
||
static_print_debug("invalid");
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void sample_avrcp_ct_release_button_rsp_cbk(const bd_addr_t *bd_addr, int32_t key_operation)
|
||
{
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("avrcp ct release button cbk key:%d", key_operation);
|
||
if (g_tjd_avrcp_srv_inf.avrcp_button_flag == AVRCP_SRV_PRESS_VALUE) {
|
||
static_print_debug("avrcp ct released button button_flag change:%u->%u", g_tjd_avrcp_srv_inf.avrcp_button_flag,
|
||
AVRCP_SRV_RELEASED_VALUE);
|
||
g_tjd_avrcp_srv_inf.avrcp_button_flag = AVRCP_SRV_RELEASED_VALUE;
|
||
}
|
||
sample_avrcp_press_release_button_log((uint32_t)key_operation);
|
||
}
|
||
|
||
static void sample_avrcp_ct_support_company_callback(const bd_addr_t *bd_addr,
|
||
const avrcp_ct_support_company_para_t *company)
|
||
{
|
||
if (bd_addr == NULL || company == NULL || company->company_id == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("sample_avrcp_ct_get_support_company company list:");
|
||
for (uint8_t i = 0; i < company->company_num; i++) {
|
||
static_print_debug(" 0x%x ", *company->company_id);
|
||
}
|
||
}
|
||
|
||
static void sample_avrcp_ct_support_event_callback(const bd_addr_t *bd_addr, avrcp_ct_support_event_para_t *event)
|
||
{
|
||
if (bd_addr == NULL || event == NULL || event->event_id == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("sample_avrcp_ct_support_event_callback event list:");
|
||
for (uint8_t i = 0; i < event->event_num; i++) {
|
||
static_print_debug(" 0x%x ", event->event_id[i]);
|
||
}
|
||
if (g_tjd_avrcp_srv_inf.reg_cap_auto != AVRCP_CT_AUTO_REG_TYPE) {
|
||
return;
|
||
}
|
||
uint8_t avrcp_ct_cap[] = {
|
||
AVRCP_NOTIFY_EVENT_RESERVED, // 0
|
||
AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED, // 1
|
||
AVRCP_NOTIFY_EVENT_TRACK_CHANGED,
|
||
AVRCP_NOTIFY_EVENT_TRACK_REACHED_END,
|
||
AVRCP_NOTIFY_EVENT_TRACK_REACHED_START,
|
||
AVRCP_NOTIFY_EVENT_RESERVED, // 5
|
||
AVRCP_NOTIFY_EVENT_RESERVED,
|
||
AVRCP_NOTIFY_EVENT_RESERVED,
|
||
AVRCP_NOTIFY_EVENT_RESERVED,
|
||
AVRCP_NOTIFY_EVENT_NOW_PLAYING_CONTENT_CHANGED, // 9
|
||
AVRCP_NOTIFY_EVENT_AVAILABLE_PLAYERS_CHANGED, // A
|
||
AVRCP_NOTIFY_EVENT_ADDRESSED_PLAYER_CHANGED,
|
||
AVRCP_NOTIFY_EVENT_RESERVED, // 0xC
|
||
AVRCP_NOTIFY_EVENT_VOLUME_CHANGED, // 0xD
|
||
};
|
||
for (uint8_t i = 0; i < event->event_num; i++) {
|
||
if (event->event_id[i] < AVRCP_NOTIFY_EVENT_RESERVED &&
|
||
avrcp_ct_cap[event->event_id[i]] != AVRCP_NOTIFY_EVENT_RESERVED) {
|
||
avrcp_ct_register_notification(bd_addr, event->event_id[i], 0);
|
||
static_print_debug("avrcp_ct_register_notification auto reg event_id:0x%x", event->event_id[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void sample_avrcp_ct_get_element_attri_callback(const bd_addr_t *bd_addr,
|
||
avrcp_ct_element_attr_para_cb_t *attr_cb_para)
|
||
{
|
||
if (bd_addr == NULL || attr_cb_para == NULL || attr_cb_para->attr_value == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
// static_print_debug("sample_avrcp_ct_get_element_attri_callback");
|
||
for (uint8_t i = 0; i < attr_cb_para->attr_num; i++) {
|
||
// static_print_debug("attrId-charaId-valLen: 0x%x-0x%x-%u ", attr_cb_para->attr_value[i].attr_id,
|
||
// attr_cb_para->attr_value[i].character_set_id, attr_cb_para->attr_value[i].value_len);
|
||
switch (attr_cb_para->attr_value[i].attr_id) {
|
||
case AVRCP_CT_ELEMENT_ATTR_TITLE:
|
||
// static_print_debug("Attr Title:");
|
||
if (g_sync_lrc_callback != NULL) {
|
||
// static_print_debug("g_sync_lrc_callback((const char *)value);");
|
||
g_sync_lrc_callback((const char *)attr_cb_para->attr_value[i].value, isFirst);
|
||
} else {
|
||
// static_print_debug("g_sync_lrc_callback is NULL");
|
||
}
|
||
if (isFirst) {
|
||
isFirst = false;
|
||
}
|
||
break;
|
||
case AVRCP_CT_ELEMENT_ATTR_ARTIST_NAME:
|
||
// static_print_debug("Attr Name:");
|
||
break;
|
||
case AVRCP_CT_ELEMENT_ATTR_ALBUM_NAME:
|
||
// static_print_debug("Attr Album:");
|
||
break;
|
||
case AVRCP_CT_ELEMENT_ATTR_TRACK_NUMBER:
|
||
// static_print_debug("Attr Track Number:");
|
||
// uint8_t *value = (uint8_t *)(void *)osal_kmalloc(attr_cb_para->attr_value[i].value_len + 1,
|
||
// OSAL_GFP_KERNEL); if (attr_cb_para->attr_value[i].value_len > 0 && attr_cb_para->attr_value[i].value !=
|
||
// NULL) {
|
||
// if (memcpy_s(value, attr_cb_para->attr_value[i].value_len, attr_cb_para->attr_value[i].value,
|
||
// attr_cb_para->attr_value[i].value_len) != EOK) {
|
||
// osal_kfree(value);
|
||
// static_print_debug("memcpy_s fail.");
|
||
// return;
|
||
// }
|
||
// }
|
||
// value[attr_cb_para->attr_value[i].value_len] = '\0';
|
||
// static_print_debug(" %s ", value);
|
||
// osal_kfree(value);
|
||
break;
|
||
case AVRCP_CT_ELEMENT_ATTR_TOTAL_NUMBER_OF_TRACKS:
|
||
// static_print_debug("Attr Total Number Of Track:");
|
||
break;
|
||
case AVRCP_CT_ELEMENT_ATTR_TRACK_GENRE:
|
||
// static_print_debug("Attr Track GENRE:");
|
||
break;
|
||
case AVRCP_CT_ELEMENT_ATTR_TRACK_PLAYING_TIME:
|
||
// static_print_debug("Attr Track Playing Time_ms:");
|
||
break;
|
||
default:
|
||
// static_print_debug("Other:");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void sample_avrcp_ct_hdl_notify_volume_rsp_cbk(avrcp_ct_notification_value_cb_t *notification)
|
||
{
|
||
static_print_debug("Set local volume:0x%x", notification->volume); /* 注册事件后通知的音量 */
|
||
}
|
||
|
||
static void sample_avrcp_ct_notification_callback(const bd_addr_t *bd_addr, avrcp_notify_event_t event_id,
|
||
avrcp_ct_notification_value_cb_t *notification)
|
||
{
|
||
if (bd_addr == NULL || notification == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("ct notification cbk event_id:0x%x playback_position %d", event_id,
|
||
notification->playback_position);
|
||
bool notify_flag = true;
|
||
switch (event_id) {
|
||
case AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED:
|
||
static_print_debug("tg notify ct playback status changed :%u", notification->play_status);
|
||
if (g_playing_state_callback != NULL) {
|
||
static_print_debug("g_playing_state_callback");
|
||
g_playing_state_callback(notification->play_status);
|
||
}
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_VOLUME_CHANGED:
|
||
sample_avrcp_ct_hdl_notify_volume_rsp_cbk(notification);
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_NOW_PLAYING_CONTENT_CHANGED:
|
||
static_print_debug("play conent changed event_id:0x%x", event_id);
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_TRACK_CHANGED:
|
||
static_print_debug("track changed event_id:0x%x", event_id);
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_TRACK_REACHED_END:
|
||
case AVRCP_NOTIFY_EVENT_TRACK_REACHED_START:
|
||
case AVRCP_NOTIFY_EVENT_PLAYBACK_POS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_BATT_STATUS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_SYSTEM_STATUS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_AVAILABLE_PLAYERS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_ADDRESSED_PLAYER_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_UIDS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_RESERVED:
|
||
default:
|
||
notify_flag = true;
|
||
break;
|
||
}
|
||
if (notify_flag) {
|
||
static_print_debug("notify reg event_id:%u", event_id);
|
||
avrcp_ct_register_notification(bd_addr, event_id, 0); /* TG通知变化后CT重新注册事件 */
|
||
avrcp_ct_get_element_attr_para_t element_attr_param;
|
||
element_attr_param.attr_num = AVRCP_CT_ELEMENT_ATTR_TRACK_PLAYING_TIME;
|
||
element_attr_param.attr_id_list =
|
||
(unsigned int *)(void *)malloc(sizeof(unsigned int) * element_attr_param.attr_num);
|
||
for (int i = 0; i < element_attr_param.attr_num; i++) {
|
||
element_attr_param.attr_id_list[i] = (unsigned int)i + 1;
|
||
}
|
||
avrcp_ct_get_element_attributes(bd_addr, &element_attr_param);
|
||
if (element_attr_param.attr_id_list != NULL) {
|
||
free(element_attr_param.attr_id_list);
|
||
element_attr_param.attr_id_list = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void sample_avrcp_ct_get_play_status_callback(const bd_addr_t *bd_addr, const avrcp_ct_play_status_cb_t *status)
|
||
{
|
||
if (bd_addr == NULL || status == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("test get play status songlen:%u, songpos:%u, playstatus:%u:", status->song_length,
|
||
status->song_position, status->play_status);
|
||
// if() {
|
||
// isFirst = true;
|
||
// }
|
||
}
|
||
|
||
void register_avrcp_ct_servers_callbacks(void)
|
||
{
|
||
static avrcp_ct_callbacks_t g_sample_avrcp_ct_bts_cbk = {
|
||
sample_avrcp_ct_connect_state_changed_callback, sample_avrcp_ct_press_button_rsp_cbk,
|
||
sample_avrcp_ct_release_button_rsp_cbk, sample_avrcp_ct_support_company_callback,
|
||
sample_avrcp_ct_support_event_callback, sample_avrcp_ct_get_element_attri_callback,
|
||
sample_avrcp_ct_get_play_status_callback, sample_avrcp_ct_notification_callback,
|
||
};
|
||
int ret = avrcp_ct_register_callbacks(&g_sample_avrcp_ct_bts_cbk);
|
||
if (ret != ERRCODE_SUCC) {
|
||
static_print_debug("avrcp_ct_register_callbacks fail:%d", ret);
|
||
}
|
||
}
|
||
#pragma endregion
|
||
|
||
#pragma region AVRCP TG SERVERS
|
||
/***************************************************************
|
||
* AVRCP TG SERVERS
|
||
*/
|
||
static void sample_avrcp_tg_connect_state_changed_callback(const bd_addr_t *bd_addr, profile_connect_state_t state)
|
||
{
|
||
if (bd_addr == NULL) {
|
||
static_print_debug("null pointer");
|
||
return;
|
||
}
|
||
static_print_debug("avrcp tg update conn stat:%u", state);
|
||
if (memcpy_s(&g_tjd_avrcp_srv_inf.bd_addr, BD_ADDR_LEN, bd_addr->addr, BD_ADDR_LEN) != EOK) {
|
||
static_print_debug("memcpy_s fail.");
|
||
return;
|
||
}
|
||
g_tjd_avrcp_srv_inf.avrcp_srv_conn_stat = state;
|
||
static_print_debug("addr: ****%02x%02x%02x%02x ", bd_addr->addr[3], bd_addr->addr[2], bd_addr->addr[1],
|
||
bd_addr->addr[0]); /* 3 2 1 0 idx */
|
||
}
|
||
|
||
void register_avrcp_tg_servers_callbacks(void)
|
||
{
|
||
static avrcp_tg_callbacks_t g_sample_avrcp_tg_bts_cbk = {
|
||
sample_avrcp_tg_connect_state_changed_callback,
|
||
};
|
||
int ret = avrcp_tg_register_callbacks(&g_sample_avrcp_tg_bts_cbk);
|
||
if (ret != ERRCODE_SUCC) {
|
||
static_print_debug("avrcp_tg_register_callbacks fail:%d", ret);
|
||
}
|
||
}
|
||
|
||
static void sample_avrcp_set_notify(bt_avrcp_tg_evt_status_param *notify_event_status_param,
|
||
avrcp_notify_event_t event_id, uint8_t event_status)
|
||
{
|
||
notify_event_status_param->event_id = event_id;
|
||
notify_event_status_param->event_status[0] = event_status;
|
||
}
|
||
|
||
static void avrcp_tg_notify_press_button_callback(uint32_t key_operation, uint32_t key_value)
|
||
{
|
||
bt_avrcp_tg_evt_status_param param;
|
||
static_print_debug("sample_avcrp_tg_notify:key_type:%u", key_operation);
|
||
// sample_avrcp_press_release_button_log(key_operation);
|
||
switch (key_operation) {
|
||
case AVRCP_KEY_VOLUME_UP:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_VOLUME_CHANGED, g_avrcp_srv_sample_inf.loc_volume);
|
||
break;
|
||
case AVRCP_KEY_VOLUME_DOWN:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_VOLUME_CHANGED, g_avrcp_srv_sample_inf.loc_volume);
|
||
break;
|
||
case AVRCP_KEY_MUTE:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_VOLUME_CHANGED, 0x0);
|
||
break;
|
||
case AVRCP_KEY_PLAY:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED, AVRCP_PLAY_STATUS_PLAYING);
|
||
break;
|
||
case AVRCP_KEY_STOP:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED, AVRCP_PLAY_STATUS_STOPPED);
|
||
break;
|
||
case AVRCP_KEY_PAUSE:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED, AVRCP_PLAY_STATUS_PAUSED);
|
||
break;
|
||
case AVRCP_KEY_FORWARD:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED, AVRCP_PLAY_STATUS_FWD_SEEK);
|
||
break;
|
||
case AVRCP_KEY_BACKWARD:
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED, AVRCP_PLAY_STATUS_REV_SEEK);
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_VOLUME_CHANGED:
|
||
static_print_debug("set absolute volume:%u", key_value);
|
||
|
||
// sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_VOLUME_CHANGED, (uint8_t)key_value);
|
||
break;
|
||
default:
|
||
sample_avrcp_set_notify(¶m, AVRCP_NOTIFY_EVENT_RESERVED, AVRCP_PLAY_STATUS_ERROR);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void avrcp_tg_get_loc_media_status_callback(bt_avrcp_tg_evt_status_param *event_status_param)
|
||
{
|
||
if (event_status_param == NULL) {
|
||
return;
|
||
}
|
||
event_status_param->event_status[0] = 0xff;
|
||
uint8_t stream_stat;
|
||
switch (event_status_param->event_id) {
|
||
case AVRCP_NOTIFY_EVENT_PLAYBACK_STATUS_CHANGED:
|
||
stream_stat = a2dp_src_get_stream_status();
|
||
if (stream_stat == SAMPLE_A2DP_STREAM_START) {
|
||
event_status_param->event_status[0] = AVRCP_PLAY_STATUS_PLAYING;
|
||
} else if (stream_stat == SAMPLE_A2DP_STREAM_SUSPENDED) {
|
||
event_status_param->event_status[0] = AVRCP_PLAY_STATUS_PAUSED;
|
||
} else {
|
||
event_status_param->event_status[0] = AVRCP_PLAY_STATUS_STOPPED;
|
||
}
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_TRACK_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_TRACK_REACHED_END:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_TRACK_REACHED_START:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_PLAYBACK_POS_CHANGED:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_BATT_STATUS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_SYSTEM_STATUS_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
|
||
case AVRCP_NOTIFY_EVENT_NOW_PLAYING_CONTENT_CHANGED:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_AVAILABLE_PLAYERS_CHANGED:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_ADDRESSED_PLAYER_CHANGED:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_UIDS_CHANGED:
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_VOLUME_CHANGED:
|
||
static_print_debug("avrcp_tg_get_loc_media_status_callback: volume:%u", event_status_param->event_status[0]);
|
||
// event_status_param->event_status[0] = avrcp_tg_get_loc_media_volume();
|
||
break;
|
||
case AVRCP_NOTIFY_EVENT_RESERVED:
|
||
default:
|
||
break;
|
||
}
|
||
static_print_debug("sample_avrcp_tg_get_loc_media_status_callback event_id:0x%x event_status:%u",
|
||
event_status_param->event_id, event_status_param->event_status[0]);
|
||
}
|
||
|
||
void register_bt_avrcp_tg_bts_callback(void)
|
||
{
|
||
static bt_avrcp_tg_bts_cbk g_sample_avrcp_tg_callbacks = {
|
||
avrcp_tg_notify_press_button_callback,
|
||
avrcp_tg_get_loc_media_status_callback,
|
||
};
|
||
bt_avrcp_tg_register_audio_cbk(&g_sample_avrcp_tg_callbacks);
|
||
}
|
||
#pragma endregion
|
||
|
||
void register_playing_state_callback(playing_state_callback_t callback)
|
||
{
|
||
static_print_debug("register_playing_state_callback");
|
||
g_playing_state_callback = callback;
|
||
}
|
||
|
||
void unregister_playing_state_callback(void) { g_playing_state_callback = NULL; }
|
||
|
||
void register_snk_connect_state_callback(snk_connect_state_callback_t callback)
|
||
{
|
||
static_print_debug("g_snk_connect_state_callback");
|
||
g_snk_connect_state_callback = callback;
|
||
}
|
||
|
||
void unregister_snk_connect_state_callback(void) { g_snk_connect_state_callback = NULL; }
|
||
|
||
void register_src_connect_state_callback(src_connect_state_callback_t callback)
|
||
{
|
||
g_src_connect_state_callback = callback;
|
||
}
|
||
|
||
void unregister_src_connect_state_callback(void) { g_src_connect_state_callback = NULL; }
|
||
|
||
void register_sync_lrc_callback(sync_lrc_callback_t callback)
|
||
{
|
||
static_print_debug("g_sync_lrc_callback");
|
||
g_sync_lrc_callback = callback;
|
||
}
|
||
|
||
void unregister_sync_lrc_callback(void) { g_sync_lrc_callback = NULL; }
|