From: Jo?o Paulo Rechi Vita <jprvita@xxxxxxxxxxxxx> --- src/modules/bluetooth/module-bluez5-device.c | 73 ++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c index b10799f..2a260f0 100644 --- a/src/modules/bluetooth/module-bluez5-device.c +++ b/src/modules/bluetooth/module-bluez5-device.c @@ -221,6 +221,18 @@ static pa_available_t get_port_availability(struct userdata *u, pa_direction_t d } /* Run from main thread */ +static pa_available_t transport_state_to_availability(pa_bluetooth_transport_state_t state) { + switch (state) { + case PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED: + return PA_AVAILABLE_NO; + case PA_BLUETOOTH_TRANSPORT_STATE_PLAYING: + return PA_AVAILABLE_YES; + default: + return PA_AVAILABLE_UNKNOWN; + } +} + +/* Run from main thread */ static void create_card_ports(struct userdata *u, pa_hashmap *ports) { pa_device_port *port; pa_device_port_new_data port_data; @@ -312,6 +324,49 @@ static void create_card_ports(struct userdata *u, pa_hashmap *ports) { } /* Run from main thread */ +static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid, pa_hashmap *ports) { + pa_device_port *input_port, *output_port; + pa_card_profile *cp = NULL; + pa_bluetooth_profile_t *p; + + pa_assert(u->input_port_name); + pa_assert(u->output_port_name); + pa_assert_se(input_port = pa_hashmap_get(ports, u->input_port_name)); + pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name)); + + if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK)) { + /* TODO: Change this profile's name to a2dp_sink, to reflect the remote + * device's role and be consistent with the a2dp source profile */ + cp = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP Sink)"), sizeof(pa_bluetooth_profile_t)); + cp->priority = 10; + cp->n_sinks = 1; + cp->n_sources = 0; + cp->max_sink_channels = 2; + cp->max_source_channels = 0; + pa_hashmap_put(output_port->profiles, cp->name, cp); + + p = PA_CARD_PROFILE_DATA(cp); + *p = PA_BLUETOOTH_PROFILE_A2DP_SINK; + } else if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE)) { + cp = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP Source)"), sizeof(pa_bluetooth_profile_t)); + cp->priority = 10; + cp->n_sinks = 0; + cp->n_sources = 1; + cp->max_sink_channels = 0; + cp->max_source_channels = 2; + pa_hashmap_put(input_port->profiles, cp->name, cp); + + p = PA_CARD_PROFILE_DATA(cp); + *p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE; + } + + if (cp && u->device->transports[*p]) + cp->available = transport_state_to_availability(u->device->transports[*p]->state); + + return cp; +} + +/* Run from main thread */ static int add_card(struct userdata *u) { const pa_bluetooth_device *d; pa_card_new_data data; @@ -319,6 +374,8 @@ static int add_card(struct userdata *u) { pa_bluetooth_form_factor_t ff; pa_card_profile *cp; pa_bluetooth_profile_t *p; + const char *uuid; + void *state; pa_assert(u); pa_assert(u->device); @@ -349,6 +406,22 @@ static int add_card(struct userdata *u) { create_card_ports(u, data.ports); + PA_HASHMAP_FOREACH(uuid, d->uuids, state) { + cp = create_card_profile(u, uuid, data.ports); + + if (!cp) + continue; + + if (pa_hashmap_get(data.profiles, cp->name)) { + pa_card_profile_free(cp); + continue; + } + + pa_hashmap_put(data.profiles, cp->name, cp); + } + + pa_assert(!pa_hashmap_isempty(data.profiles)); + cp = pa_card_profile_new("off", _("Off"), sizeof(pa_bluetooth_profile_t)); cp->available = PA_AVAILABLE_YES; p = PA_CARD_PROFILE_DATA(cp); -- 1.8.3.1