mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
bluez: implement profile on device
Enumerate the available profiles on the device. Make params visible. Implement set_profile, only expose the nodes that belong to the profile.
This commit is contained in:
parent
5f70a2713e
commit
9db240e786
3 changed files with 90 additions and 35 deletions
|
|
@ -911,6 +911,7 @@ static int impl_node_send_command(void *object, const struct spa_command *comman
|
||||||
if ((res = do_start(this)) < 0)
|
if ((res = do_start(this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
break;
|
break;
|
||||||
|
case SPA_NODE_COMMAND_Suspend:
|
||||||
case SPA_NODE_COMMAND_Pause:
|
case SPA_NODE_COMMAND_Pause:
|
||||||
if ((res = do_stop(this)) < 0)
|
if ((res = do_stop(this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,10 @@ struct impl {
|
||||||
|
|
||||||
struct spa_bt_device *bt_dev;
|
struct spa_bt_device *bt_dev;
|
||||||
|
|
||||||
uint32_t next_id;
|
|
||||||
uint32_t profile;
|
uint32_t profile;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void emit_node (struct impl *this, struct spa_bt_transport *t, const char *factory_name)
|
static void emit_node (struct impl *this, struct spa_bt_transport *t, uint32_t id, const char *factory_name)
|
||||||
{
|
{
|
||||||
struct spa_device_object_info info;
|
struct spa_device_object_info info;
|
||||||
struct spa_dict_item items[2];
|
struct spa_dict_item items[2];
|
||||||
|
|
@ -93,37 +92,72 @@ static void emit_node (struct impl *this, struct spa_bt_transport *t, const char
|
||||||
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
|
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
|
||||||
info.props = &SPA_DICT_INIT_ARRAY(items);
|
info.props = &SPA_DICT_INIT_ARRAY(items);
|
||||||
|
|
||||||
spa_device_emit_object_info(&this->hooks, this->next_id++, &info);
|
spa_device_emit_object_info(&this->hooks, id, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int emit_nodes(struct impl *this)
|
static struct spa_bt_transport *find_transport(struct impl *this, int profile)
|
||||||
{
|
{
|
||||||
struct spa_bt_device *device = this->bt_dev;
|
struct spa_bt_device *device = this->bt_dev;
|
||||||
struct spa_bt_transport *t;
|
struct spa_bt_transport *t;
|
||||||
|
|
||||||
spa_list_for_each(t, &device->transport_list, device_link) {
|
spa_list_for_each(t, &device->transport_list, device_link) {
|
||||||
if (t->profile & device->connected_profiles) {
|
if (t->profile & device->connected_profiles &&
|
||||||
switch (t->profile) {
|
(t->profile & profile) == t->profile)
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int emit_nodes(struct impl *this)
|
||||||
|
{
|
||||||
|
struct spa_bt_transport *t;
|
||||||
|
|
||||||
|
t = find_transport(this, this->profile);
|
||||||
|
if (t == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (this->profile) {
|
||||||
case SPA_BT_PROFILE_A2DP_SOURCE:
|
case SPA_BT_PROFILE_A2DP_SOURCE:
|
||||||
emit_node (this, t, SPA_NAME_API_BLUEZ5_A2DP_SOURCE);
|
emit_node(this, t, 0, SPA_NAME_API_BLUEZ5_A2DP_SOURCE);
|
||||||
break;
|
break;
|
||||||
case SPA_BT_PROFILE_A2DP_SINK:
|
case SPA_BT_PROFILE_A2DP_SINK:
|
||||||
emit_node (this, t, SPA_NAME_API_BLUEZ5_A2DP_SINK);
|
emit_node(this, t, 0, SPA_NAME_API_BLUEZ5_A2DP_SINK);
|
||||||
break;
|
break;
|
||||||
case SPA_BT_PROFILE_HSP_HS:
|
case SPA_BT_PROFILE_HSP_HS:
|
||||||
case SPA_BT_PROFILE_HSP_AG:
|
case SPA_BT_PROFILE_HSP_AG:
|
||||||
case SPA_BT_PROFILE_HFP_HF:
|
case SPA_BT_PROFILE_HFP_HF:
|
||||||
case SPA_BT_PROFILE_HFP_AG:
|
case SPA_BT_PROFILE_HFP_AG:
|
||||||
emit_node (this, t, SPA_NAME_API_BLUEZ5_SCO_SOURCE);
|
emit_node(this, t, 0, SPA_NAME_API_BLUEZ5_SCO_SOURCE);
|
||||||
emit_node (this, t, SPA_NAME_API_BLUEZ5_SCO_SINK);
|
emit_node(this, t, 1, SPA_NAME_API_BLUEZ5_SCO_SINK);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_profile(struct impl *this, uint32_t profile)
|
||||||
|
{
|
||||||
|
if (this->profile == profile)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
switch (this->profile) {
|
||||||
|
case SPA_BT_PROFILE_A2DP_SOURCE:
|
||||||
|
case SPA_BT_PROFILE_A2DP_SINK:
|
||||||
|
spa_device_emit_object_info(&this->hooks, 0, NULL);
|
||||||
|
break;
|
||||||
|
case SPA_BT_PROFILE_HSP_HS:
|
||||||
|
case SPA_BT_PROFILE_HSP_AG:
|
||||||
|
case SPA_BT_PROFILE_HFP_HF:
|
||||||
|
case SPA_BT_PROFILE_HFP_AG:
|
||||||
|
spa_device_emit_object_info(&this->hooks, 0, NULL);
|
||||||
|
spa_device_emit_object_info(&this->hooks, 1, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->profile = profile;
|
||||||
|
return emit_nodes(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct spa_dict_item info_items[] = {
|
static const struct spa_dict_item info_items[] = {
|
||||||
|
|
@ -146,6 +180,7 @@ static int impl_add_listener(void *object,
|
||||||
|
|
||||||
if (events->info) {
|
if (events->info) {
|
||||||
struct spa_device_info info;
|
struct spa_device_info info;
|
||||||
|
struct spa_param_info params[2];
|
||||||
|
|
||||||
info = SPA_DEVICE_INFO_INIT();
|
info = SPA_DEVICE_INFO_INIT();
|
||||||
|
|
||||||
|
|
@ -153,8 +188,10 @@ static int impl_add_listener(void *object,
|
||||||
info.props = &SPA_DICT_INIT_ARRAY(info_items);
|
info.props = &SPA_DICT_INIT_ARRAY(info_items);
|
||||||
|
|
||||||
info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
|
info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
|
||||||
info.n_params = 0;
|
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumProfile, SPA_PARAM_INFO_READ);
|
||||||
info.params = NULL;
|
params[1] = SPA_PARAM_INFO(SPA_PARAM_Profile, SPA_PARAM_INFO_READWRITE);
|
||||||
|
info.n_params = SPA_N_ELEMENTS(params);
|
||||||
|
info.params = params;
|
||||||
|
|
||||||
spa_device_emit_info(&this->hooks, &info);
|
spa_device_emit_info(&this->hooks, &info);
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +215,18 @@ static int impl_sync(void *object, int seq)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int maskn(int v, int n)
|
||||||
|
{
|
||||||
|
int pos = 0, cnt = 0;
|
||||||
|
while (v) {
|
||||||
|
if ((v & 1) == 1 && (++cnt == n))
|
||||||
|
return 1 << pos;
|
||||||
|
v >>= 1;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int impl_enum_params(void *object, int seq,
|
static int impl_enum_params(void *object, int seq,
|
||||||
uint32_t id, uint32_t start, uint32_t num,
|
uint32_t id, uint32_t start, uint32_t num,
|
||||||
const struct spa_pod *filter)
|
const struct spa_pod *filter)
|
||||||
|
|
@ -188,6 +237,7 @@ static int impl_enum_params(void *object, int seq,
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_result_device_params result;
|
struct spa_result_device_params result;
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
struct spa_bt_device *device = this->bt_dev;
|
||||||
|
|
||||||
spa_return_val_if_fail(this != NULL, -EINVAL);
|
spa_return_val_if_fail(this != NULL, -EINVAL);
|
||||||
spa_return_val_if_fail(num != 0, -EINVAL);
|
spa_return_val_if_fail(num != 0, -EINVAL);
|
||||||
|
|
@ -202,6 +252,8 @@ static int impl_enum_params(void *object, int seq,
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case SPA_PARAM_EnumProfile:
|
case SPA_PARAM_EnumProfile:
|
||||||
{
|
{
|
||||||
|
int profile;
|
||||||
|
|
||||||
switch (result.index) {
|
switch (result.index) {
|
||||||
case 0:
|
case 0:
|
||||||
param = spa_pod_builder_add_object(&b,
|
param = spa_pod_builder_add_object(&b,
|
||||||
|
|
@ -209,14 +261,18 @@ static int impl_enum_params(void *object, int seq,
|
||||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(0),
|
SPA_PARAM_PROFILE_index, SPA_POD_Int(0),
|
||||||
SPA_PARAM_PROFILE_name, SPA_POD_String("Off"));
|
SPA_PARAM_PROFILE_name, SPA_POD_String("Off"));
|
||||||
break;
|
break;
|
||||||
case 1:
|
default:
|
||||||
|
{
|
||||||
|
profile = maskn(device->connected_profiles, result.index);
|
||||||
|
if (profile == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
param = spa_pod_builder_add_object(&b,
|
param = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_ParamProfile, id,
|
SPA_TYPE_OBJECT_ParamProfile, id,
|
||||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(1),
|
SPA_PARAM_PROFILE_index, SPA_POD_Int(profile),
|
||||||
SPA_PARAM_PROFILE_name, SPA_POD_String("On"));
|
SPA_PARAM_PROFILE_name, SPA_POD_String(spa_bt_profile_name(profile)));
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +326,7 @@ static int impl_set_param(void *object,
|
||||||
spa_debug_pod(0, NULL, param);
|
spa_debug_pod(0, NULL, param);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
set_profile(this, id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -352,8 +408,6 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
|
|
||||||
reset_props(&this->props);
|
reset_props(&this->props);
|
||||||
|
|
||||||
this->next_id = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,8 @@ extern "C" {
|
||||||
|
|
||||||
enum spa_bt_profile {
|
enum spa_bt_profile {
|
||||||
SPA_BT_PROFILE_NULL = 0,
|
SPA_BT_PROFILE_NULL = 0,
|
||||||
SPA_BT_PROFILE_A2DP_SOURCE = (1 << 0),
|
SPA_BT_PROFILE_A2DP_SINK = (1 << 0),
|
||||||
SPA_BT_PROFILE_A2DP_SINK = (1 << 1),
|
SPA_BT_PROFILE_A2DP_SOURCE = (1 << 1),
|
||||||
SPA_BT_PROFILE_HSP_HS = (1 << 2),
|
SPA_BT_PROFILE_HSP_HS = (1 << 2),
|
||||||
SPA_BT_PROFILE_HSP_AG = (1 << 3),
|
SPA_BT_PROFILE_HSP_AG = (1 << 3),
|
||||||
SPA_BT_PROFILE_HFP_HF = (1 << 4),
|
SPA_BT_PROFILE_HFP_HF = (1 << 4),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue