summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTanu Kaskinen <tanu.kaskinen@digia.com>2011-03-31 15:00:52 +0300
committerColin Guthrie <colin@mageia.org>2011-04-01 13:33:50 +0100
commit35c93f711df803cee81a4753700f1fe2ec73bf21 (patch)
tree73f56d2f0a3e176c8b9db563c5b1eb431b30d227
parentccbf7a3006abfda81cb891a68625a9304689b352 (diff)
bluetooth: Fix HSP volume handling.
Previously the userdata for the volume callbacks was saved to pa_core.shared only once when loading module-bluetooth-device, and only when the SCO over PCM feature was used. That breaks volume handling in cases where the HSP profile is used without the SCO over PCM setup. Now the userdata is set always when a sink or source is created, and removed when a sink or source is removed.
-rw-r--r--src/modules/bluetooth/module-bluetooth-device.c101
1 files changed, 69 insertions, 32 deletions
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index b0e0a7b4..e4a2ceff 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1959,6 +1959,8 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct
/* Run from main thread */
static int add_sink(struct userdata *u) {
+ char *k;
+
if (USE_SCO_OVER_PCM(u)) {
pa_proplist *p;
@@ -2012,6 +2014,10 @@ static int add_sink(struct userdata *u) {
if (u->profile == PROFILE_HSP) {
u->sink->set_volume = sink_set_volume_cb;
u->sink->n_volume_steps = 16;
+
+ k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink);
+ pa_shared_set(u->core, k, u);
+ pa_xfree(k);
}
return 0;
@@ -2019,6 +2025,8 @@ static int add_sink(struct userdata *u) {
/* Run from main thread */
static int add_source(struct userdata *u) {
+ char *k;
+
if (USE_SCO_OVER_PCM(u)) {
u->source = u->hsp.sco_source;
pa_proplist_sets(u->source->proplist, "bluetooth.protocol", "hsp");
@@ -2077,6 +2085,10 @@ static int add_source(struct userdata *u) {
if (u->profile == PROFILE_HSP) {
u->source->set_volume = source_set_volume_cb;
u->source->n_volume_steps = 16;
+
+ k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source);
+ pa_shared_set(u->core, k, u);
+ pa_xfree(k);
}
return 0;
@@ -2323,6 +2335,8 @@ static int init_profile(struct userdata *u) {
/* Run from main thread */
static void stop_thread(struct userdata *u) {
+ char *k;
+
pa_assert(u);
if (u->thread) {
@@ -2347,11 +2361,23 @@ static void stop_thread(struct userdata *u) {
}
if (u->sink) {
+ if (u->profile == PROFILE_HSP) {
+ k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink);
+ pa_shared_remove(u->core, k);
+ pa_xfree(k);
+ }
+
pa_sink_unref(u->sink);
u->sink = NULL;
}
if (u->source) {
+ if (u->profile == PROFILE_HSP) {
+ k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source);
+ pa_shared_remove(u->core, k);
+ pa_xfree(k);
+ }
+
pa_source_unref(u->source);
u->source = NULL;
}
@@ -2381,8 +2407,20 @@ static int start_thread(struct userdata *u) {
if (USE_SCO_OVER_PCM(u)) {
if (sco_over_pcm_state_update(u) < 0) {
- u->sink = NULL;
- u->source = NULL;
+ char *k;
+
+ if (u->sink) {
+ k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink);
+ pa_shared_remove(u->core, k);
+ pa_xfree(k);
+ 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);
+ u->source = NULL;
+ }
return -1;
}
@@ -2419,6 +2457,22 @@ static int start_thread(struct userdata *u) {
return 0;
}
+static void save_sco_volume_callbacks(struct userdata *u) {
+ pa_assert(u);
+ pa_assert(USE_SCO_OVER_PCM(u));
+
+ u->hsp.sco_sink_set_volume = u->hsp.sco_sink->set_volume;
+ u->hsp.sco_source_set_volume = u->hsp.sco_source->set_volume;
+}
+
+static void restore_sco_volume_callbacks(struct userdata *u) {
+ pa_assert(u);
+ pa_assert(USE_SCO_OVER_PCM(u));
+
+ u->hsp.sco_sink->set_volume = u->hsp.sco_sink_set_volume;
+ u->hsp.sco_source->set_volume = u->hsp.sco_source_set_volume;
+}
+
/* Run from main thread */
static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
struct userdata *u;
@@ -2472,9 +2526,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
stop_thread(u);
shutdown_bt(u);
+ if (USE_SCO_OVER_PCM(u))
+ restore_sco_volume_callbacks(u);
+
u->profile = *d;
u->sample_spec = u->requested_sample_spec;
+ if (USE_SCO_OVER_PCM(u))
+ save_sco_volume_callbacks(u);
+
init_bt(u);
if (u->profile != PROFILE_OFF)
@@ -2639,6 +2699,9 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
d = PA_CARD_PROFILE_DATA(u->card->active_profile);
u->profile = *d;
+ if (USE_SCO_OVER_PCM(u))
+ save_sco_volume_callbacks(u);
+
return 0;
}
@@ -2702,7 +2765,7 @@ int pa__init(pa_module* m) {
struct userdata *u;
const char *address, *path;
DBusError err;
- char *mike, *speaker, *transport, *k;
+ char *mike, *speaker, *transport;
const pa_bluetooth_device *device;
pa_assert(m);
@@ -2803,20 +2866,6 @@ int pa__init(pa_module* m) {
/* Connect to the BT service */
init_bt(u);
- if (u->hsp.sco_sink) {
- u->hsp.sco_sink_set_volume = u->hsp.sco_sink->set_volume;
- k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->hsp.sco_sink);
- pa_shared_set(u->core, k, u);
- pa_xfree(k);
- }
-
- if (u->hsp.sco_source) {
- u->hsp.sco_source_set_volume = u->hsp.sco_source->set_volume;
- k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->hsp.sco_source);
- pa_shared_set(u->core, k, u);
- pa_xfree(k);
- }
-
if (u->profile != PROFILE_OFF)
if (init_profile(u) < 0)
goto fail;
@@ -2849,7 +2898,6 @@ int pa__get_n_used(pa_module *m) {
void pa__done(pa_module *m) {
struct userdata *u;
- char *k;
pa_assert(m);
@@ -2864,6 +2912,9 @@ void pa__done(pa_module *m) {
stop_thread(u);
+ if (USE_SCO_OVER_PCM(u))
+ restore_sco_volume_callbacks(u);
+
if (u->connection) {
if (u->path) {
@@ -2891,20 +2942,6 @@ void pa__done(pa_module *m) {
shutdown_bt(u);
- if (u->hsp.sco_sink) {
- u->hsp.sco_sink->set_volume = u->hsp.sco_sink_set_volume;
- k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->hsp.sco_sink);
- pa_shared_remove(u->core, k);
- pa_xfree(k);
- }
-
- if (u->hsp.sco_source) {
- u->hsp.sco_source->set_volume = u->hsp.sco_source_set_volume;
- k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->hsp.sco_source);
- pa_shared_remove(u->core, k);
- pa_xfree(k);
- }
-
if (u->a2dp.buffer)
pa_xfree(u->a2dp.buffer);