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.
This commit is contained in:
Tanu Kaskinen 2011-03-31 15:00:52 +03:00 committed by Colin Guthrie
parent ccbf7a3006
commit 35c93f711d

View file

@ -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) {
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);