bluez: add sco-sink and sco-source nodes

This commit is contained in:
Julian Bouzas 2019-07-31 12:11:56 -04:00 committed by Wim Taymans
parent d274497e3c
commit de031b42b1
6 changed files with 2356 additions and 102 deletions

View file

@ -87,8 +87,10 @@ extern "C" {
/** keys for bluez5 factory names */
#define SPA_NAME_API_BLUEZ5_MONITOR "api.bluez5.monitor" /**< a Monitor interface */
#define SPA_NAME_API_BLUEZ5_DEVICE "api.bluez5.device" /**< a Device interface */
#define SPA_NAME_API_BLUEZ5_A2DP_SINK "api.bluez5.a2dp.sink" /**< a playback Node interface */
#define SPA_NAME_API_BLUEZ5_A2DP_SOURCE "api.bluez5.a2dp.source" /**< a capture Node interface */
#define SPA_NAME_API_BLUEZ5_A2DP_SINK "api.bluez5.a2dp.sink" /**< a playback Node interface for A2DP profiles */
#define SPA_NAME_API_BLUEZ5_A2DP_SOURCE "api.bluez5.a2dp.source" /**< a capture Node interface for A2DP profiles */
#define SPA_NAME_API_BLUEZ5_SCO_SINK "api.bluez5.sco.sink" /**< a playback Node interface for HSP/HFP profiles */
#define SPA_NAME_API_BLUEZ5_SCO_SOURCE "api.bluez5.sco.source" /**< a capture Node interface for HSP/HFP profiles */
/** keys for v4l2 factory names */
#define SPA_NAME_API_V4L2_MONITOR "api.v4l2.monitor" /**< a v4l2 Monitor interface */

View file

@ -67,118 +67,56 @@ struct impl {
struct props props;
struct spa_bt_device *bt_dev;
uint32_t next_id;
};
static int emit_source_node(struct impl *this)
static void emit_node (struct impl *this, struct spa_bt_transport *t, const char *factory_name)
{
struct spa_dict_item items[1];
struct spa_bt_transport *t;
struct spa_bt_device *device = this->bt_dev;
enum spa_bt_profile profile = SPA_BT_PROFILE_NULL;
struct spa_device_object_info info;
struct spa_dict_item items[1];
char transport[32];
if (device->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE) {
spa_log_info(this->log, "device %p: A2DP (source) profile found",
device);
profile = SPA_BT_PROFILE_A2DP_SOURCE;
} else if (device->connected_profiles & SPA_BT_PROFILE_HSP_HS) {
spa_log_info(this->log, "device %p: HSP (source) profile found (Not implemented yet)",
device);
profile = SPA_BT_PROFILE_HSP_HS;
return -ENODEV;
} else if (device->connected_profiles & SPA_BT_PROFILE_HFP_HF) {
spa_log_info(this->log, "device %p: HFP (source) profile found (Not implemented yet)",
device);
profile = SPA_BT_PROFILE_HFP_HF;
return -ENODEV;
}
snprintf(transport, sizeof(transport), "pointer:%p", t);
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_API_BLUEZ5_TRANSPORT, transport);
/* Return if no profiles are connected */
if (profile == SPA_BT_PROFILE_NULL)
return -ENODEV;
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Node;
info.factory_name = factory_name;
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(items);
spa_list_for_each(t, &device->transport_list, device_link) {
if (t->profile == profile) {
struct spa_device_object_info info;
char transport[32];
snprintf(transport, sizeof(transport), "pointer:%p", t);
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_API_BLUEZ5_TRANSPORT, transport);
spa_bt_transport_acquire(t, true);
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Node;
info.factory_name = SPA_NAME_API_BLUEZ5_A2DP_SOURCE;
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(items);
spa_device_emit_object_info(&this->hooks, 0, &info);
break;
}
}
spa_log_info (this->log, "device %p: bluez5 source nodes emitted", device);
return 0;
}
static int emit_sink_node(struct impl *this)
{
struct spa_dict_item items[1];
struct spa_bt_transport *t;
struct spa_bt_device *device = this->bt_dev;
enum spa_bt_profile profile = SPA_BT_PROFILE_NULL;
if (device->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) {
spa_log_info(this->log, "A2DP (sink) profile found");
profile = SPA_BT_PROFILE_A2DP_SINK;
} else if (device->connected_profiles & SPA_BT_PROFILE_HSP_AG) {
spa_log_info(this->log, "HSP (sink) profile found (Not implemented yet)");
profile = SPA_BT_PROFILE_HSP_AG;
return -ENODEV;
} else if (device->connected_profiles & SPA_BT_PROFILE_HFP_AG) {
spa_log_info(this->log, "HFP (sink) profile found (Not implemented yet)");
profile = SPA_BT_PROFILE_HFP_AG;
return -ENODEV;
}
/* Return if no profiles are connected */
if (profile == SPA_BT_PROFILE_NULL)
return -ENODEV;
spa_list_for_each(t, &device->transport_list, device_link) {
if (t->profile == profile) {
struct spa_device_object_info info;
char transport[32];
snprintf(transport, sizeof(transport), "pointer:%p", t);
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_API_BLUEZ5_TRANSPORT, transport);
info = SPA_DEVICE_OBJECT_INFO_INIT();
info.type = SPA_TYPE_INTERFACE_Node;
info.factory_name = SPA_NAME_API_BLUEZ5_A2DP_SINK;
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(items);
spa_device_emit_object_info(&this->hooks, 0, &info);
break;
}
}
spa_log_info(this->log, "bluez5 sink nodes emitted");
return 0;
spa_device_emit_object_info(&this->hooks, this->next_id++, &info);
}
static int emit_nodes(struct impl *this)
{
int sink, src;
struct spa_bt_device *device = this->bt_dev;
struct spa_bt_transport *t;
sink = emit_sink_node(this);
src = emit_source_node(this);
spa_list_for_each(t, &device->transport_list, device_link) {
if (t->profile & device->connected_profiles) {
switch (t->profile) {
case SPA_BT_PROFILE_A2DP_SOURCE:
emit_node (this, t, SPA_NAME_API_BLUEZ5_A2DP_SOURCE);
break;
case SPA_BT_PROFILE_A2DP_SINK:
emit_node (this, t, SPA_NAME_API_BLUEZ5_A2DP_SINK);
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:
emit_node (this, t, SPA_NAME_API_BLUEZ5_SCO_SOURCE);
emit_node (this, t, SPA_NAME_API_BLUEZ5_SCO_SINK);
break;
default:
return -EINVAL;
}
}
}
if (sink == -ENODEV && src == -ENODEV)
spa_log_warn(this->log, "no profile available");
return SPA_MAX(sink, src);
return 0;
}
static const struct spa_dict_item info_items[] = {
@ -316,6 +254,8 @@ impl_init(const struct spa_handle_factory *factory,
reset_props(&this->props);
this->next_id = 0;
return 0;
}

View file

@ -3,6 +3,8 @@ bluez5_sources = ['plugin.c',
'a2dp-codecs.c',
'a2dp-sink.c',
'a2dp-source.c',
'sco-sink.c',
'sco-source.c',
'bluez5-device.c',
'bluez5-monitor.c']

View file

@ -31,6 +31,8 @@ extern const struct spa_handle_factory spa_bluez5_monitor_factory;
extern const struct spa_handle_factory spa_bluez5_device_factory;
extern const struct spa_handle_factory spa_a2dp_sink_factory;
extern const struct spa_handle_factory spa_a2dp_source_factory;
extern const struct spa_handle_factory spa_sco_sink_factory;
extern const struct spa_handle_factory spa_sco_source_factory;
SPA_EXPORT
int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
@ -51,6 +53,12 @@ int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t
case 3:
*factory = &spa_a2dp_source_factory;
break;
case 4:
*factory = &spa_sco_sink_factory;
break;
case 5:
*factory = &spa_sco_source_factory;
break;
default:
return 0;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff