From: Jo?o Paulo Rechi Vita <jprvita@xxxxxxxxxxxxx> --- src/modules/bluetooth/module-bluez5-device.c | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c index 310e9ef..1ea8894 100644 --- a/src/modules/bluetooth/module-bluez5-device.c +++ b/src/modules/bluetooth/module-bluez5-device.c @@ -222,6 +222,18 @@ static pa_available_t get_port_availability(struct userdata *u, pa_direction_t d } /* Run from main thread */ +static pa_available_t pa_bluetooth_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; @@ -310,6 +322,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, A2DP_SINK_UUID)) { + /* 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 = PROFILE_A2DP_SINK; + } else if (pa_streq(uuid, A2DP_SOURCE_UUID)) { + 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 = PROFILE_A2DP_SOURCE; + } + + if (cp && u->device->transports[*p]) + cp->available = pa_bluetooth_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; @@ -317,6 +372,7 @@ static int add_card(struct userdata *u) { pa_bluetooth_form_factor_t ff; pa_card_profile *cp; pa_bluetooth_profile_t *p; + const pa_bluetooth_uuid *uuid; pa_assert(u); pa_assert(u->device); @@ -347,6 +403,22 @@ static int add_card(struct userdata *u) { create_card_ports(u, data.ports); + PA_LLIST_FOREACH(uuid, d->uuids) { + cp = create_card_profile(u, uuid->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.7.11.7