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 */
|
||||
#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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
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