[pulseaudio-discuss] [PATCH 09/11] bluetooth: Add device prototype support
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Sat Nov 23 21:58:06 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 | 59 +++++++++++++++++++++++--
1 file changed, 55 insertions(+), 4 deletions(-)
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index e51da4d..db2c5ff 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -35,6 +35,7 @@
#include <pulse/timeval.h>
#include <pulse/xmalloc.h>
+#include <pulsecore/device-prototype.h>
#include <pulsecore/i18n.h>
#include <pulsecore/module.h>
#include <pulsecore/modargs.h>
@@ -156,6 +157,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 +1584,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 +1658,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 +1883,19 @@ 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_device_prototype_set_sink(u->sink_prototype, NULL);
+ else
+ 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_device_prototype_set_source(u->source_prototype, NULL);
+ else
+ pa_source_unlink(u->source);
+ }
if (u->thread) {
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
@@ -1951,19 +1966,25 @@ static int start_thread(struct userdata *u) {
k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink);
pa_shared_remove(u->core, k);
pa_xfree(k);
+ pa_device_prototype_set_sink(u->sink_prototype, NULL);
u->sink = NULL;
}
if (u->source) {
k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source);
pa_shared_remove(u->core, k);
pa_xfree(k);
+ pa_device_prototype_set_source(u->source_prototype, NULL);
u->source = NULL;
}
return -1;
}
pa_sink_ref(u->sink);
+ pa_device_prototype_set_sink(u->sink_prototype, u->sink);
+
pa_source_ref(u->source);
+ pa_device_prototype_set_source(u->source_prototype, u->source);
+
/* FIXME: monitor stream_fd error */
return 0;
}
@@ -2192,8 +2213,12 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name));
if (pa_streq(uuid, A2DP_SINK_UUID)) {
+ if (!u->sink_prototype)
+ u->sink_prototype = pa_device_prototype_new();
+
p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(enum profile));
p->priority = 10;
+ pa_hashmap_put(p->device_prototypes, u->sink_prototype, u->sink_prototype);
p->n_sinks = 1;
p->n_sources = 0;
p->max_sink_channels = 2;
@@ -2203,8 +2228,12 @@ 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)) {
+ if (!u->source_prototype)
+ u->source_prototype = pa_device_prototype_new();
+
p = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP)"), sizeof(enum profile));
p->priority = 10;
+ pa_hashmap_put(p->device_prototypes, u->source_prototype, u->source_prototype);
p->n_sinks = 0;
p->n_sources = 1;
p->max_sink_channels = 0;
@@ -2214,8 +2243,16 @@ 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)) {
+ if (!u->sink_prototype)
+ u->sink_prototype = pa_device_prototype_new();
+
+ if (!u->source_prototype)
+ u->source_prototype = pa_device_prototype_new();
+
p = pa_card_profile_new("hsp", _("Telephony Duplex (HSP/HFP)"), sizeof(enum profile));
p->priority = 20;
+ pa_hashmap_put(p->device_prototypes, u->sink_prototype, u->sink_prototype);
+ pa_hashmap_put(p->device_prototypes, u->source_prototype, u->source_prototype);
p->n_sinks = 1;
p->n_sources = 1;
p->max_sink_channels = 1;
@@ -2226,8 +2263,16 @@ 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)) {
+ if (!u->sink_prototype)
+ u->sink_prototype = pa_device_prototype_new();
+
+ if (!u->source_prototype)
+ u->source_prototype = pa_device_prototype_new();
+
p = pa_card_profile_new("hfgw", _("Handsfree Gateway"), sizeof(enum profile));
p->priority = 20;
+ pa_hashmap_put(p->device_prototypes, u->sink_prototype, u->sink_prototype);
+ pa_hashmap_put(p->device_prototypes, u->source_prototype, u->source_prototype);
p->n_sinks = 1;
p->n_sources = 1;
p->max_sink_channels = 1;
@@ -2628,6 +2673,12 @@ void pa__done(pa_module *m) {
if (u->card)
pa_card_free(u->card);
+ if (u->source_prototype)
+ pa_device_prototype_free(u->source_prototype);
+
+ if (u->sink_prototype)
+ pa_device_prototype_free(u->sink_prototype);
+
if (u->a2dp.buffer)
pa_xfree(u->a2dp.buffer);
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list