[pulseaudio-discuss] [PATCH v2 07/10] bluetooth: Add device prototype support
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Mon Dec 9 10:31:44 PST 2013
There is only one sink prototype and only one source prototype,
because regardless of the chosen profile, the sink and source will
always use the same name, therefore they should be treated as the same
entity.
In the "SCO over PCM" mode we have to manage the sink/source pointer
lifecycle in the prototypes ourselves, because the SCO sink and source
are actually ALSA devices that exist all the time. They are not
removed from the system when changing to the A2DP profile.
---
src/modules/bluetooth/module-bluetooth-device.c | 52 +++++++++++++++++++++----
1 file changed, 44 insertions(+), 8 deletions(-)
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index bfd0f99..cfa8b8d 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -156,6 +156,8 @@ struct userdata {
char *input_port_name;
pa_card *card;
+ pa_device_prototype *sink_prototype;
+ pa_device_prototype *source_prototype;
pa_sink *sink;
pa_source *source;
@@ -1581,6 +1583,8 @@ static int add_sink(struct userdata *u) {
pa_assert_not_reached();
}
+ pa_sink_new_data_set_prototype(&data, u->sink_prototype);
+
u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
pa_sink_new_data_done(&data);
@@ -1653,6 +1657,8 @@ static int add_source(struct userdata *u) {
pa_assert_not_reached();
}
+ pa_source_new_data_set_prototype(&data, u->source_prototype);
+
u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
pa_source_new_data_done(&data);
@@ -1876,11 +1882,15 @@ static void stop_thread(struct userdata *u) {
pa_assert(u);
- if (u->sink && !USE_SCO_OVER_PCM(u))
- pa_sink_unlink(u->sink);
+ if (u->sink) {
+ if (!USE_SCO_OVER_PCM(u))
+ pa_sink_unlink(u->sink);
+ }
- if (u->source && !USE_SCO_OVER_PCM(u))
- pa_source_unlink(u->source);
+ if (u->source) {
+ if (!USE_SCO_OVER_PCM(u))
+ pa_source_unlink(u->source);
+ }
if (u->thread) {
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
@@ -2182,6 +2192,7 @@ fail:
/* Run from main thread */
static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid, pa_hashmap *ports) {
+ enum profile profile = PROFILE_OFF;
pa_device_port *input_port, *output_port;
pa_card_profile *p = NULL;
enum profile *d;
@@ -2191,9 +2202,29 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
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)) {
+ if (pa_streq(uuid, A2DP_SINK_UUID))
+ profile = PROFILE_A2DP;
+ else if (pa_streq(uuid, A2DP_SOURCE_UUID))
+ profile = PROFILE_A2DP_SOURCE;
+ else if (pa_streq(uuid, HSP_HS_UUID) || pa_streq(uuid, HFP_HS_UUID))
+ profile = PROFILE_HSP;
+ else if (pa_streq(uuid, HFP_AG_UUID))
+ profile = PROFILE_HFGW;
+
+ if (profile == PROFILE_A2DP || (!USE_SCO_OVER_PCM(u) && (profile == PROFILE_HSP || profile == PROFILE_HFGW))) {
+ if (!u->sink_prototype)
+ u->sink_prototype = pa_device_prototype_new(PA_DIRECTION_OUTPUT);
+ }
+
+ if (profile == PROFILE_A2DP_SOURCE || (!USE_SCO_OVER_PCM(u) && (profile == PROFILE_HSP || profile == PROFILE_HFGW))) {
+ if (!u->source_prototype)
+ u->source_prototype = pa_device_prototype_new(PA_DIRECTION_INPUT);
+ }
+
+ if (profile == PROFILE_A2DP) {
p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(enum profile));
p->priority = 10;
+ pa_hashmap_put(p->sink_prototypes, u->sink_prototype, u->sink_prototype);
p->n_sinks = 1;
p->n_sources = 0;
p->max_sink_channels = 2;
@@ -2202,9 +2233,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
d = PA_CARD_PROFILE_DATA(p);
*d = PROFILE_A2DP;
- } else if (pa_streq(uuid, A2DP_SOURCE_UUID)) {
+ } else if (profile == PROFILE_A2DP_SOURCE) {
p = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP)"), sizeof(enum profile));
p->priority = 10;
+ pa_hashmap_put(p->source_prototypes, u->source_prototype, u->source_prototype);
p->n_sinks = 0;
p->n_sources = 1;
p->max_sink_channels = 0;
@@ -2213,11 +2245,13 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
d = PA_CARD_PROFILE_DATA(p);
*d = PROFILE_A2DP_SOURCE;
- } else if (pa_streq(uuid, HSP_HS_UUID) || pa_streq(uuid, HFP_HS_UUID)) {
+ } else if (profile == PROFILE_HSP) {
p = pa_card_profile_new("hsp", _("Telephony Duplex (HSP/HFP)"), sizeof(enum profile));
p->priority = 20;
if (!USE_SCO_OVER_PCM(u)) {
+ pa_hashmap_put(p->sink_prototypes, u->sink_prototype, u->sink_prototype);
+ pa_hashmap_put(p->source_prototypes, u->source_prototype, u->source_prototype);
p->n_sinks = 1;
p->n_sources = 1;
p->max_sink_channels = 1;
@@ -2229,11 +2263,13 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
d = PA_CARD_PROFILE_DATA(p);
*d = PROFILE_HSP;
- } else if (pa_streq(uuid, HFP_AG_UUID)) {
+ } else if (profile == PROFILE_HFGW) {
p = pa_card_profile_new("hfgw", _("Handsfree Gateway"), sizeof(enum profile));
p->priority = 20;
if (!USE_SCO_OVER_PCM(u)) {
+ pa_hashmap_put(p->sink_prototypes, u->sink_prototype, u->sink_prototype);
+ pa_hashmap_put(p->source_prototypes, u->source_prototype, u->source_prototype);
p->n_sinks = 1;
p->n_sources = 1;
p->max_sink_channels = 1;
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list