On 06/04/2012 07:35 PM, poljar wrote: > The bluetooth device should have ports so we can attach a latency to > the ports. I think it is good that we create ports for more types of devices, but I don't see how that correlates to different latencies...? > Every profile (a2dp, hsp...) has his own set of ports depending on the > number of sinks and sources it provides. > --- > src/modules/bluetooth/module-bluetooth-device.c | 124 +++++++++++++++++++++++ > 1 file changed, 124 insertions(+) > > diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c > index 68c4efc..4901ef9 100644 > --- a/src/modules/bluetooth/module-bluetooth-device.c > +++ b/src/modules/bluetooth/module-bluetooth-device.c > @@ -2073,6 +2073,61 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct > return PA_HOOK_OK; > } > > +static void connect_ports(struct userdata *u, void *sink_or_source_new_data, pa_direction_t direction) { > + union { > + pa_sink_new_data *sink_new_data; > + pa_source_new_data *source_new_data; > + } data; Using unions this way is error-prone IMO - just use two different pointers "sink_new_data" and "source_new_data", no point in encapsulating them into "data". > + pa_device_port *port; > + > + if (direction == PA_DIRECTION_OUTPUT) { > + data.sink_new_data = sink_or_source_new_data; > + data.sink_new_data->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); > + } else { > + data.source_new_data = sink_or_source_new_data; > + data.source_new_data->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); > + } > + > + switch (u->profile) { > + case PROFILE_A2DP: > + pa_assert_se(port = pa_hashmap_get(u->card->ports, "a2dp-output")); > + pa_assert_se(pa_hashmap_put(data.sink_new_data->ports, port->name, port)>= 0); > + pa_device_port_ref(port); > + break; This might be something I'm not seeing here, but you're ref-ing the port here, but where is it unref-ed so it can be freed properly? > + > + case PROFILE_A2DP_SOURCE: > + pa_assert_se(port = pa_hashmap_get(u->card->ports, "a2dp-input")); > + pa_assert_se(pa_hashmap_put(data.source_new_data->ports, port->name, port)>= 0); > + pa_device_port_ref(port); > + break; > + > + case PROFILE_HSP: > + if (direction == PA_DIRECTION_OUTPUT) { > + pa_assert_se(port = pa_hashmap_get(u->card->ports, "hsp-output")); > + pa_assert_se(pa_hashmap_put(data.sink_new_data->ports, port->name, port)>= 0); > + } else { > + pa_assert_se(port = pa_hashmap_get(u->card->ports, "hsp-input")); > + pa_assert_se(pa_hashmap_put(data.source_new_data->ports, port->name, port)>= 0); > + } > + pa_device_port_ref(port); > + break; > + > + case PROFILE_HFGW: > + if (direction == PA_DIRECTION_OUTPUT) { > + pa_assert_se(port = pa_hashmap_get(u->card->ports, "hfgw-output")); > + pa_assert_se(pa_hashmap_put(data.sink_new_data->ports, port->name, port)>= 0); > + } else { > + pa_assert_se(port = pa_hashmap_get(u->card->ports, "hfgw-input")); > + pa_assert_se(pa_hashmap_put(data.source_new_data->ports, port->name, port)>= 0); > + } > + pa_device_port_ref(port); > + break; > + > + default: > + pa_assert_not_reached(); > + } > +} > + > /* Run from main thread */ > static int add_sink(struct userdata *u) { > char *k; > @@ -2109,6 +2164,7 @@ static int add_sink(struct userdata *u) { > pa_sink_new_data_done(&data); > return -1; > } > + connect_ports(u,&data, PA_DIRECTION_OUTPUT); > > u->sink = pa_sink_new(u->core,&data, PA_SINK_HARDWARE|PA_SINK_LATENCY); > pa_sink_new_data_done(&data); > @@ -2172,6 +2228,7 @@ static int add_source(struct userdata *u) { > return -1; > } > > + connect_ports(u,&data, PA_DIRECTION_INPUT); > u->source = pa_source_new(u->core,&data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY); > pa_source_new_data_done(&data); > > @@ -2696,6 +2753,69 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { > return 0; > } > > +static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_new_data, pa_card_profile *profile) { > + pa_device_port *port; > + enum profile *d; > + > + d = PA_CARD_PROFILE_DATA(profile); > + > + switch (*d) { > + case PROFILE_A2DP: > + pa_assert_se(port = pa_device_port_new(u->core, "a2dp-output", _("Bluetooth High Quality (A2DP)"), 0)); > + pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port)>= 0); > + port->is_output = 1; > + port->is_input = 0; > + port->priority = profile->priority * 100; > + pa_hashmap_put(port->profiles, profile->name, profile); > + break; > + > + case PROFILE_A2DP_SOURCE: > + pa_assert_se(port = pa_device_port_new(u->core, "a2dp-input", _("Bluetooth High Quality (A2DP)"), 0)); > + pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port)>= 0); > + port->is_output = 0; > + port->is_input = 1; > + port->priority = profile->priority * 100; > + pa_hashmap_put(port->profiles, profile->name, profile); > + break; > + > + case PROFILE_HSP: > + pa_assert_se(port = pa_device_port_new(u->core, "hsp-output", _("Bluetooth Telephony (HSP/HFP)"), 0)); > + pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port)>= 0); > + port->is_output = 1; > + port->is_input = 0; > + port->priority = profile->priority * 100; > + pa_hashmap_put(port->profiles, profile->name, profile); > + > + pa_assert_se(port = pa_device_port_new(u->core, "hsp-input", _("Bluetooth Telephony (HSP/HFP)"), 0)); > + pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port)>= 0); > + port->is_output = 0; > + port->is_input = 1; > + port->priority = profile->priority * 100; > + pa_hashmap_put(port->profiles, profile->name, profile); > + break; > + > + case PROFILE_HFGW: > + pa_assert_se(port = pa_device_port_new(u->core, "hfgw-output", _("Bluetooth Handsfree Gateway"), 0)); > + pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port)>= 0); > + port->is_output = 1; > + port->is_input = 0; > + port->priority = profile->priority * 100; > + pa_hashmap_put(port->profiles, profile->name, profile); > + > + pa_assert_se(port = pa_device_port_new(u->core, "hfgw-input", _("Bluetooth Handsfree Gateway"), 0)); > + pa_assert_se(pa_hashmap_put(card_new_data->ports, port->name, port)>= 0); > + port->is_output = 0; > + port->is_input = 1; > + port->priority = profile->priority * 100; > + pa_hashmap_put(port->profiles, profile->name, profile); > + break; > + > + default: > + pa_assert_not_reached(); > + } > + > +} > + > /* Run from main thread */ > static int add_card(struct userdata *u, const pa_bluetooth_device *device) { > pa_card_new_data data; > @@ -2750,6 +2870,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) { > > d = PA_CARD_PROFILE_DATA(p); > *d = PROFILE_A2DP; > + create_ports_for_profile(u,&data, p); > > pa_hashmap_put(data.profiles, p->name, p); > } > @@ -2764,6 +2885,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) { > > d = PA_CARD_PROFILE_DATA(p); > *d = PROFILE_A2DP_SOURCE; > + create_ports_for_profile(u,&data, p); > > pa_hashmap_put(data.profiles, p->name, p); > } > @@ -2779,6 +2901,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) { > > d = PA_CARD_PROFILE_DATA(p); > *d = PROFILE_HSP; > + create_ports_for_profile(u,&data, p); > > pa_hashmap_put(data.profiles, p->name, p); > } > @@ -2793,6 +2916,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) { > > d = PA_CARD_PROFILE_DATA(p); > *d = PROFILE_HFGW; > + create_ports_for_profile(u,&data, p); > > pa_hashmap_put(data.profiles, p->name, p); > } -- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic