mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
bluez: add sco-sink and sco-source nodes
This commit is contained in:
parent
d274497e3c
commit
de031b42b1
6 changed files with 2356 additions and 102 deletions
|
|
@ -87,8 +87,10 @@ extern "C" {
|
||||||
/** keys for bluez5 factory names */
|
/** keys for bluez5 factory names */
|
||||||
#define SPA_NAME_API_BLUEZ5_MONITOR "api.bluez5.monitor" /**< a Monitor interface */
|
#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_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_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 */
|
#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 */
|
/** keys for v4l2 factory names */
|
||||||
#define SPA_NAME_API_V4L2_MONITOR "api.v4l2.monitor" /**< a v4l2 Monitor interface */
|
#define SPA_NAME_API_V4L2_MONITOR "api.v4l2.monitor" /**< a v4l2 Monitor interface */
|
||||||
|
|
|
||||||
|
|
@ -67,118 +67,56 @@ struct impl {
|
||||||
struct props props;
|
struct props props;
|
||||||
|
|
||||||
struct spa_bt_device *bt_dev;
|
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_device_object_info info;
|
||||||
struct spa_bt_transport *t;
|
struct spa_dict_item items[1];
|
||||||
struct spa_bt_device *device = this->bt_dev;
|
char transport[32];
|
||||||
enum spa_bt_profile profile = SPA_BT_PROFILE_NULL;
|
|
||||||
|
|
||||||
if (device->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE) {
|
snprintf(transport, sizeof(transport), "pointer:%p", t);
|
||||||
spa_log_info(this->log, "device %p: A2DP (source) profile found",
|
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_API_BLUEZ5_TRANSPORT, transport);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return if no profiles are connected */
|
info = SPA_DEVICE_OBJECT_INFO_INIT();
|
||||||
if (profile == SPA_BT_PROFILE_NULL)
|
info.type = SPA_TYPE_INTERFACE_Node;
|
||||||
return -ENODEV;
|
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) {
|
spa_device_emit_object_info(&this->hooks, this->next_id++, &info);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int emit_nodes(struct impl *this)
|
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);
|
spa_list_for_each(t, &device->transport_list, device_link) {
|
||||||
src = emit_source_node(this);
|
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)
|
return 0;
|
||||||
spa_log_warn(this->log, "no profile available");
|
|
||||||
|
|
||||||
return SPA_MAX(sink, src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct spa_dict_item info_items[] = {
|
static const struct spa_dict_item info_items[] = {
|
||||||
|
|
@ -316,6 +254,8 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
|
|
||||||
reset_props(&this->props);
|
reset_props(&this->props);
|
||||||
|
|
||||||
|
this->next_id = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ bluez5_sources = ['plugin.c',
|
||||||
'a2dp-codecs.c',
|
'a2dp-codecs.c',
|
||||||
'a2dp-sink.c',
|
'a2dp-sink.c',
|
||||||
'a2dp-source.c',
|
'a2dp-source.c',
|
||||||
|
'sco-sink.c',
|
||||||
|
'sco-source.c',
|
||||||
'bluez5-device.c',
|
'bluez5-device.c',
|
||||||
'bluez5-monitor.c']
|
'bluez5-monitor.c']
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_bluez5_device_factory;
|
||||||
extern const struct spa_handle_factory spa_a2dp_sink_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_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
|
SPA_EXPORT
|
||||||
int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
|
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:
|
case 3:
|
||||||
*factory = &spa_a2dp_source_factory;
|
*factory = &spa_a2dp_source_factory;
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
*factory = &spa_sco_sink_factory;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
*factory = &spa_sco_source_factory;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1186
spa/plugins/bluez5/sco-sink.c
Normal file
1186
spa/plugins/bluez5/sco-sink.c
Normal file
File diff suppressed because it is too large
Load diff
1116
spa/plugins/bluez5/sco-source.c
Normal file
1116
spa/plugins/bluez5/sco-source.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue